﻿/*
 * Copyright (C) 2023, KylinSoft Co., Ltd.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, see <http://www.gnu.org/licenses/>.
 *
**/
#include "widget.h"
#include "controlpanel.h"
#include "declarative/qmloutput.h"
#include "declarative/qmlscreen.h"
#include "utils.h"
#include "ui_display.h"
#include "displayperformancedialog.h"
#include "colorinfo.h"
#include "scalesize.h"
#include "ukcccommon.h"
using namespace ukcc;

#include <QHBoxLayout>
#include <QTimer>
#include <QLabel>
#include <QVBoxLayout>
#include <QSplitter>
#include <QtGlobal>
#include <QQuickView>
#include <qquickitem.h>
#include <QDebug>
#include <QPushButton>
#include <QProcess>
#include <QtAlgorithms>
#include <QtXml>
#include <QDomDocument>
#include <QDir>
#include <QStandardPaths>
#include <QComboBox>
#include <QQuickWidget>
#include <QMessageBox>
#include <QDBusConnection>
#include <QJsonDocument>
#include <QtConcurrent>
#include <QVariantMap>
#include <QDBusMetaType>
#include <unistd.h>
#include <QListView>
#include <QStandardItem>

#include <KF5/KScreen/kscreen/output.h>
#include <KF5/KScreen/kscreen/edid.h>
#include <KF5/KScreen/kscreen/mode.h>
#include <KF5/KScreen/kscreen/config.h>
#include <KF5/KScreen/kscreen/getconfigoperation.h>
#include <KF5/KScreen/kscreen/configmonitor.h>
#include <KF5/KScreen/kscreen/setconfigoperation.h>
#include <KF5/KScreen/kscreen/edid.h>
#include <KF5/KScreen/kscreen/types.h>

#include <math.h>
#ifdef KY_SDK_SYSINFO
#include <kysdk/kysdk-system/libkysysinfo.h>
#endif

#ifdef signals
#undef signals
#endif

#define UKUI_CONTORLCENTER_PANEL_SCHEMAS "org.ukui.control-center.panel.plugins"
#define THEME_NIGHT_KEY                  "themebynight"

#define FONT_RENDERING_DPI               "org.ukui.SettingsDaemon.plugins.xsettings"
#define SCALE_KEY                        "scaling-factor"

#define USD_BRIGHT_SCHEMAS               "org.ukui.SettingsDaemon.plugins.auto-brightness"
#define BRIGHT_KEY                       "auto-brightness"
#define DYNAMIC_BRIHT_KEY                "dynamic-brightness"

#define SETTINGS_DAEMON_COLOR_SCHEMAS    "org.ukui.SettingsDaemon.plugins.color"
#define AUTO_KEY                         "night-light-schedule-automatic"
#define AllDAY_KEY                       "night-light-allday"
#define NIGHT_ENABLE_KEY                 "night-light-enabled"
#define NIGHT_FROM_KEY                   "night-light-schedule-from"
#define NIGHT_TO_KEY                     "night-light-schedule-to"
#define AUTO_NIGHT_FROM_KEY              "night-light-schedule-automatic-from"
#define AUTO_NIGHT_TO_KEY                "night-light-schedule-automatic-to"
#define NIGHT_TEMPERATURE_KEY            "night-light-temperature"
#define EYES_MODE                        "eye-care"

#define MOUSE_SIZE_SCHEMAS               "org.ukui.peripherals-mouse"
#define CURSOR_SIZE_KEY                  "cursor-size"

#define POWER_SCHMES                     "org.ukui.power-manager"
#define POWER_KEY                        "brightness-ac"

#define ADVANCED_SCHEMAS                 "org.ukui.session.required-components"
#define ADVANCED_KEY                     "windowmanager"

const QString kCpu = "ZHAOXIN";
const QString kLoong = "Loongson";
const QString tempDayBrig = "6500";

void value_to_hour_minute(double value, int *hour, int *minute)
{
    double hours;
    double mins = 0.f;
    /* display the right thing for AM/PM */
    mins = modf (value, &hours) * 60.f;
    *hour = int(hours);
    *minute = int(mins);
}

double hour_minute_to_value(int hour, int minute) {
    double value = (double)minute/60;
    return (double)hour + value;
}

Q_DECLARE_METATYPE(KScreen::OutputPtr)

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::DisplayWindow())
{
    cpuArchitecture = UkccCommon::getCpuArchitecture();
    qRegisterMetaType<QQuickView *>();

    ui->setupUi(this);
    initUi();
    initNightModeUi();
    initAutoBrihgtUI();
    initSpliceFrame();
    initDbusComponent();
    ui->quickWidget->setResizeMode(QQuickWidget::SizeRootObjectToView);
    ui->quickWidget->setContentsMargins(0, 0, 0, 9);
    spliceDialog = new SpliceDialog(this);
    qDBusRegisterMetaType<ScreenConfig>();
    firstAddOutputName = "";
    connectedOutputNum = 0;
    initComponent();
    setHideModuleInfo();

    initGSettings();
    setNightComponent();
    initUiComponent();
    initNightStatus();

    initConnection();
    loadQml();

    hideComponent();

    mScreenScale = scaleGSettings->get(SCALE_KEY).toDouble();
}

Widget::~Widget()
{
    for (BrightnessFrame *m_frame : BrightnessFrameV) {
        if (m_frame) {
            delete m_frame;
            m_frame = nullptr;
        }
    }
    spliceDialog->deleteLater();
    clearOutputIdentifiers();
    delete ui;
    ui = nullptr;
}

bool Widget::eventFilter(QObject *object, QEvent *event)
{
    if (event->type() == QEvent::Resize) {
        if (mOutputIdentifiers.contains(qobject_cast<QQuickView *>(object))) {
            QResizeEvent *e = static_cast<QResizeEvent *>(event);
            const QRect screenSize = object->property("screenSize").toRect();
            QRect geometry(QPoint(0, 0), e->size());
            geometry.moveCenter(screenSize.center());
            static_cast<QQuickView *>(object)->setGeometry(geometry);
            // Pass the event further
        }
    }
    return QObject::eventFilter(object, event);
}

void Widget::setConfig(const KScreen::ConfigPtr &config)
{
    if (mConfig) {
        KScreen::ConfigMonitor::instance()->removeConfig(mConfig);
        for (const KScreen::OutputPtr &output : mConfig->outputs()) {
            output->disconnect(this);
        }
        mConfig->disconnect(this);
    }
    mConfig = config;
    mPrevConfig = config->clone();
    if (mMultiScreenFrame) {
        mMultiScreenFrame->setVisible(mConfig->connectedOutputs().size() > 1);
    }
    updateMultiScreen();

    KScreen::ConfigMonitor::instance()->addConfig(mConfig);
    resetPrimaryCombo();
    connect(mConfig.data(), &KScreen::Config::outputAdded,
            this, [=](const KScreen::OutputPtr &output){
        outputAdded(output, false);
    });
    connect(mConfig.data(), &KScreen::Config::outputRemoved,
            this, [=](int outputId){
        outputRemoved(outputId, false);
    });

    //connect(mConfig.data(), &KScreen::Config::primaryOutputChanged,
    //        this, &Widget::primaryOutputChanged);

    // 上面屏幕拿取配置
    mScreen->setConfig(mConfig);
    mControlPanel->setConfig(mConfig);

    for (const KScreen::OutputPtr &output : mConfig->outputs()) {
        if (false == unifySetconfig) {
            outputAdded(output, false);
        } else { //解决统一输出之后connect信号不再触发的问题
            connect(output.data(), &KScreen::Output::isConnectedChanged,
                this, &Widget::slotOutputConnectedChanged);
            connect(output.data(), &KScreen::Output::isEnabledChanged,
                this, &Widget::slotOutputEnabledChanged);
            for (QMLOutput *mOutput: mScreen->outputs()) {
                if (mOutput->outputPtr() = output) {
                    disconnect(mOutput, SIGNAL(clicked()),
                               this, SLOT(mOutputClicked())); //避免多次连接
                    connect(mOutput, SIGNAL(clicked()),
                            this, SLOT(mOutputClicked()));
                }
            }
        }
    }
   unifySetconfig = false;
    // 择主屏幕输出
    QMLOutput *qmlOutput = mScreen->primaryOutput();

    if (qmlOutput) {
        mScreen->setActiveOutput(qmlOutput);
    } else {
        if (!mScreen->outputs().isEmpty()) {
            mScreen->setActiveOutput(mScreen->outputs().at(0));
            // 择一个主屏幕，避免闪退现象
            primaryButtonEnable(true);
        }
    }
    slotOutputEnabledChanged();

    if (mFirstLoad) {
        if (mIscloneMode) {
            slotUnifyOutputs();
        }
        setMulScreenVisiable();
        changescale();
        compareScale();
        if (mIsSCaleRes) {
            mIsSCaleRes = false;
            showZoomtips();
        }
    }
    mFirstLoad = false;

}

KScreen::ConfigPtr Widget::currentConfig() const
{
    return mConfig;
}

void Widget::initNightModeUi()
{
    ui->verticalLayout->setSpacing(8);
    mNightModeLabel = new TitleLabel(this);
    //~ contents_path /Display/Night Mode
    mNightModeLabel->setText(tr("Night Mode"));
    mNightModeFrame = new SettingGroup(this);

    /*Eyes mode*/
    //~ contents_path /Display/Eye protection mode
    mEyesModeFrame =  new SwitchWidget(tr("Eye Protection Mode"), nullptr, UkccFrame::Around, tr("When turned on, it can reduce blue light to prevent eye, the screen will turn yellow."));
    mEyesModeFrame->setMinimumSize(550, 80);
    mEyesModeFrame->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
    mEyesModeFrame->setVisible(false);

    /* Open */
    mNightModeWidget = new SwitchWidget(tr("Open"), nullptr, UkccFrame::None, tr("When turned on, it will reduce the blue light of the screen."));

#ifdef Nile
    mEyesModeFrame->setVisible(true);
    //~ contents_path /Display/Color Temperature And Eye Care
    mNightModeLabel->setText(tr("Color Temperature And Eye Care"));
    //~ contents_path /Display/Color Temperature
    mNightModeWidget->setTitle(tr("Color Temperature"));
    mNightModeWidget->setHintTextVisible(false);
    ui->verticalLayout->setSpacing(16);
#endif

    /* Time Mode */
    mTimeModeWidget = new ComboxWidget(tr("Time"), this);
    mTimeModeWidget->setTitleFixedWidth(108);

    /* Custom Time */
    mCustomTimeWidget = new UkccFrame(this, UkccFrame::BorderRadiusStyle::Around, true);
    QHBoxLayout *mCustomTimeLyt = new QHBoxLayout(mCustomTimeWidget);
    mCustomTimeLyt->setContentsMargins(16, 0, 16, 0);
    mCustomTimeLyt->setSpacing(8);
    mCustomTimeLabel = new QLabel(mCustomTimeWidget);
    mCustomTimeLabel->setFixedWidth(350);
    mCustomTimeLabel->setText(tr("Custom Time"));
    mOpenTimeHCombox = new QComboBox(mCustomTimeWidget);
    mOpenTimeHCombox->setFixedWidth(64);
    mQpenTimeMCombox = new QComboBox(mCustomTimeWidget);
    mQpenTimeMCombox->setFixedWidth(64);
    mCloseTimeHCombox = new QComboBox(mCustomTimeWidget);
    mCloseTimeHCombox->setFixedWidth(64);
    mCloseTimeMCombox = new QComboBox(mCustomTimeWidget);
    mCloseTimeMCombox->setFixedWidth(64);
    mLabel_1 = new QLabel(mCustomTimeWidget);
    mLabel_1->setFixedWidth(20);
    mLabel_1->setText(tr("to"));
    QLabel *mLabel_2 = new QLabel(mCustomTimeWidget);
    mLabel_2->setFixedWidth(4);
    mLabel_2->setText(":");
    QLabel *mLabel_3 = new QLabel(mCustomTimeWidget);
    mLabel_3->setFixedWidth(4);
    mLabel_3->setText(":");
    mCustomTimeLyt->addWidget(mCustomTimeLabel);
    mCustomTimeLyt->addStretch();
    mCustomTimeLyt->addWidget(mOpenTimeHCombox);
    mCustomTimeLyt->addWidget(mLabel_2);
    mCustomTimeLyt->addWidget(mQpenTimeMCombox);
    mCustomTimeLyt->addWidget(mLabel_1);
    mCustomTimeLyt->addWidget(mCloseTimeHCombox);
    mCustomTimeLyt->addWidget(mLabel_3);
    mCustomTimeLyt->addWidget(mCloseTimeMCombox);

    /* Color Temperature */
    mTemptWidget = new SliderWidget(tr("Color Temperature"), false, this);
    mTemptWidget->setTitleFixedWidth(100);
    mTemptWidget->setLeftText(tr("Warmer"));
    mTemptWidget->setRightText(tr("Colder"));

    mNightModeFrame->addWidget(mNightModeWidget);
    mNightModeFrame->addWidget(mTimeModeWidget);
    mNightModeFrame->addWidget(mCustomTimeWidget);
    mNightModeFrame->addWidget(mTemptWidget);

    ui->verticalLayout->addWidget(mNightModeLabel);
    ui->verticalLayout->addWidget(mEyesModeFrame);
    ui->verticalLayout->addWidget(mNightModeFrame);

}

void Widget::loadQml()
{
    qmlRegisterType<QMLOutput>("org.kde.kscreen", 1, 0, "QMLOutput");
    qmlRegisterType<QMLScreen>("org.kde.kscreen", 1, 0, "QMLScreen");

    qmlRegisterType<KScreen::Output>("org.kde.kscreen", 1, 0, "KScreenOutput");
    qmlRegisterType<KScreen::Edid>("org.kde.kscreen", 1, 0, "KScreenEdid");
    qmlRegisterType<KScreen::Mode>("org.kde.kscreen", 1, 0, "KScreenMode");

    ui->quickWidget->setSource(QUrl("qrc:/qml/main.qml"));

    QQuickItem *rootObject = ui->quickWidget->rootObject();
    mScreen = rootObject->findChild<QMLScreen *>(QStringLiteral("outputView"));

    connect(mScreen, &QMLScreen::released, this, [=]() {
        delayApply();
    });

    if (!mScreen) {
        return;
    }
    connect(mScreen, &QMLScreen::focusedOutputChanged,
            this, &Widget::slotFocusedOutputChanged);
}

void Widget::resetPrimaryCombo()
{
    // Don't emit currentIndexChanged when resetting
    bool blocked = monitorComboBox->blockSignals(true);
    monitorComboBox->clear();
    monitorComboBox->blockSignals(blocked);

    if (!mConfig) {
        return;
    }

    for (auto &output: mConfig->outputs()) {
        addOutputToPrimaryCombo(output);
    }
}

void Widget::addOutputToPrimaryCombo(const KScreen::OutputPtr &output)
{
    // 注释后让他显示全部屏幕下拉框
    if (!output->isConnected()) {
        return;
    }

    monitorComboBox->addItem(Utils::outputName(output), output->id());
    if (output->isPrimary() && !mIsWayland) {
        Q_ASSERT(mConfig);
        int lastIndex = monitorComboBox->count() - 1;
        monitorComboBox->setCurrentIndex(lastIndex);
    }
}

// 这里从屏幕点击来读取输出
void Widget::slotFocusedOutputChanged(QMLOutput *output)
{
    mControlPanel->activateOutput(output->outputPtr());

    // 读取屏幕点击选择下拉框
    Q_ASSERT(mConfig);
    int index = output->outputPtr().isNull() ? 0 : monitorComboBox->findData(output->outputPtr()->id());
    if (index == -1 || index == monitorComboBox->currentIndex()) {
        return;
    }
    monitorComboBox->setCurrentIndex(index);
}

void Widget::slotFocusedOutputChangedNoParam()
{
    mControlPanel->activateOutput(res);
}

void Widget::slotOutputEnabledChanged()
{
    clearOutputIdentifiers();
    // 点击禁用屏幕输出后的改变
    resetPrimaryCombo();
    int enabledOutputsCount = 0;
    Q_FOREACH (const KScreen::OutputPtr &output, mConfig->outputs()) {
        for (int i = 0; i < BrightnessFrameV.size(); ++i) {
            if (BrightnessFrameV[i]->getOutputName() == Utils::outputName(output)) {
                BrightnessFrameV[i]->setOutputEnable(output->isEnabled());
                break;
            }
        }
        if (output->isEnabled()) {
            ++enabledOutputsCount;
            for (int i = 0; i < BrightnessFrameV.size(); ++i) {
                if (BrightnessFrameV[i]->getOutputName() == Utils::outputName(output) && !BrightnessFrameV[i]->getSliderEnable()) {
                    BrightnessFrameV[i]->runConnectThread(true);
                }
            }
        }
        if (enabledOutputsCount > 1) {
            break;
        }
    }
}

void Widget::slotOutputConnectedChanged()
{
    clearOutputIdentifiers();
    const KScreen::OutputPtr output(qobject_cast<KScreen::Output *>(sender()), [](void *){});
    if (!output) {
        return;
    }

    if (output->isConnected()) {
        outputAdded(output, true);
    } else {
        outputRemoved(output->id(), true);
    }

    updateMultiScreen();
    resetPrimaryCombo();

    // bug#89064,bug#89174
    QTimer::singleShot(500, this, [=](){
        setMulScreenVisiable();
        resetPrimaryCombo();
    });
}

void Widget::slotUnifyOutputs()
{
    bool isExtendMode = (mKdsStatus == 2);
    QMLOutput *base = mScreen->primaryOutput();

    QList<int> clones;
    if (updateScreenConfig() != 0) {
        return;
    }

    if (!base) {
        for (QMLOutput *output: mScreen->outputs()) {
            if (output->output()->isConnected() && output->output()->isEnabled()) {
                base = output;
                break;
            }
        }
        if (!base) {
            // WTF?
            return;
        }
    }
    for (QMLOutput *output: mScreen->outputs()) {
        //修改镜像时usd会修改modeId
        for (KScreen::OutputPtr m_output : mPrevConfig->connectedOutputs()) {
            if (m_output->name() == output->outputPtr()->name()) {
                output->outputPtr()->setCurrentModeId(m_output->currentModeId());
            }
        }
        if (mIscloneMode && output == base) {
            output->setIsCloneMode(true, true);
        } else {
            output->setIsCloneMode(mIscloneMode, false);
        }
    }
    // 取消统一输出
    if (!mIscloneMode) {

        unifySetconfig = true;

        setConfig(mPrevConfig);

        monitorComboBox->setEnabled(isExtendMode);
        openMonitorFrame->setVisible(mPrevConfig->connectedOutputs().count() > 1);
    } else if (mIscloneMode) {
        // Clone the current config, so that we can restore it in case user
        // breaks the cloning

        for (QMLOutput *output: mScreen->outputs()) {
            if (output != base) {
                output->output()->setRotation(base->output()->rotation());
            }

            if (!output->output()->isConnected()) {
                continue;
            }

            if (!output->output()->isEnabled()) {
                continue;
            }

            if (!base) {
                base = output;
            }

            output->setOutputX(0);
            output->setOutputY(0);
            output->output()->setPos(QPoint(0, 0));
            output->output()->setClones(QList<int>());

            if (base != output) {
                clones << output->output()->id();
                output->setCloneOf(base);
            }
        }

        base->output()->setClones(clones);
        mScreen->updateOutputsPlacement();

        // 关闭开关
        openMonitorButton->setEnabled(false);
        openMonitorFrame->setVisible(false);
        monitorComboBox->setEnabled(false);
        monitorBtn->setVisible(false);
        mControlPanel->setUnifiedOutput(base->outputPtr());
    }
}

// FIXME: Copy-pasted from KDED's Serializer::findOutput()
KScreen::OutputPtr Widget::findOutput(const KScreen::ConfigPtr &config, const QVariantMap &info)
{
    KScreen::OutputList outputs = config->outputs();
    Q_FOREACH (const KScreen::OutputPtr &output, outputs) {
        if (!output->isConnected()) {
            continue;
        }

        const QString outputId
            = (output->edid()
               && output->edid()->isValid()) ? output->edid()->hash() : output->name();
        if (outputId != info[QStringLiteral("id")].toString()) {
            continue;
        }

        QVariantMap posInfo = info[QStringLiteral("pos")].toMap();
        QPoint point(posInfo[QStringLiteral("x")].toInt(), posInfo[QStringLiteral("y")].toInt());
        output->setPos(point);
        output->setPrimary(info[QStringLiteral("primary")].toBool());
        output->setEnabled(info[QStringLiteral("enabled")].toBool());
        output->setRotation(static_cast<KScreen::Output::Rotation>(info[QStringLiteral("rotation")].
                                                                   toInt()));

        QVariantMap modeInfo = info[QStringLiteral("mode")].toMap();
        QVariantMap modeSize = modeInfo[QStringLiteral("size")].toMap();
        QSize size(modeSize[QStringLiteral("width")].toInt(),
                   modeSize[QStringLiteral("height")].toInt());

        const KScreen::ModeList modes = output->modes();
        Q_FOREACH (const KScreen::ModePtr &mode, modes) {
            if (mode->size() != size) {
                continue;
            }
            if (QString::number(mode->refreshRate())
                != modeInfo[QStringLiteral("refresh")].toString()) {
                continue;
            }

            output->setCurrentModeId(mode->id());
            break;
        }
        return output;
    }

    return KScreen::OutputPtr();
}

void Widget::initComponent()
{
    QHBoxLayout *multiScreenlay = new QHBoxLayout();
    mMultiScreenLabel = new QLabel(tr("Multi-screen"), this);
    mMultiScreenLabel->setFixedSize(108, 30);

    mMultiScreenCombox = new QComboBox(this);
#ifndef MAVIS
    mMultiScreenCombox->addItem(tr("First Screen"));
    mMultiScreenCombox->addItem(tr("Vice Screen"));
#endif
    mMultiScreenCombox->addItem(tr("Extend Screen"));
    mMultiScreenCombox->addItem(tr("Clone Screen"));
#ifndef BUILD_NO_SPLICE_SCREEN
    mMultiScreenCombox->addItem(tr("Splice Screen"));
#endif
    multiScreenlay->setContentsMargins(16, 0, 16, 0);
    multiScreenlay->setSpacing(16);
    multiScreenlay->addWidget(mMultiScreenLabel);
    multiScreenlay->addWidget(mMultiScreenCombox);

    mMultiScreenFrame->setLayout(multiScreenlay);
    mMultiScreenFrame->setVisible(false);

    if (m_StatusDbus->isValid()) {
        QDBusReply<bool> is_tabletmode = m_StatusDbus->call("get_current_tabletmode");
        if (is_tabletmode) {
            mMultiScreenCombox->setEnabled(false);
        }
    }
}

void Widget::initDbusComponent()
{
    dbusEdid = new QDBusInterface("org.kde.KScreen",
            "/backend",
            "org.kde.kscreen.Backend",
            QDBusConnection::sessionBus());

    mUsdDbus = new QDBusInterface("org.ukui.SettingsDaemon",
                                  "/org/ukui/SettingsDaemon/xrandr",
                                  "org.ukui.SettingsDaemon.xrandr",
                                  QDBusConnection::sessionBus(), this);


    if (mUsdDbus->isValid()) {
        QDBusReply<int> reply = mUsdDbus->call("getScreenMode", "ukui-control-center");
        mKdsStatus = reply.value();
        (reply == USD_CLONE_MODE) ? mIscloneMode = true : mIscloneMode = false;
    }

    m_StatusDbus = new QDBusInterface("com.kylin.statusmanager.interface",
                                      "/",
                                      "com.kylin.statusmanager.interface",
                                      QDBusConnection::sessionBus(), this);
}

void Widget::setHideModuleInfo()
{
    mCPU = getCpuInfo();
    //fix bug#78013
    ui->quickWidget->setAttribute(Qt::WA_AlwaysStackOnTop);
    ui->quickWidget->setClearColor(Qt::transparent);
}

void Widget::writeScale(double scale)
{
    if (scale != scaleGSettings->get(SCALE_KEY).toDouble()) {
        mIsScaleChanged = true;
    }

    if (mIsScaleChanged) {
        QStringList keys = scaleGSettings->keys();
        if (keys.contains("scalingFactor")) {
            scaleGSettings->set(SCALE_KEY, scale);
        }
        if (!mIsChange) {  //主动切换缩放率，直接提示注销
            showZoomtips();
        } else {
            mIsChange = false;
        }
        mIsScaleChanged = false;

    }
}

void Widget::initGSettings()
{
    QByteArray nightId(SETTINGS_DAEMON_COLOR_SCHEMAS);
    if(QGSettings::isSchemaInstalled(nightId)) {
        m_colorSettings = new QGSettings(nightId);

        if (m_colorSettings) {
            connect(m_colorSettings, &QGSettings::changed, [=](const QString &key){
                if(key == "nightLightTemperature")
                {
                    int value = m_colorSettings->get(NIGHT_TEMPERATURE_KEY).toInt();
                    mTemptWidget->setValue(value);
                }
                else if(key == "nightLightScheduleAutomatic" || key == "nightLightEnabled" || key == "nightLightAllday") {
                    setNightModeSetting();
                }
            });
        }

    } else {
        qDebug() << Q_FUNC_INFO << "org.ukui.SettingsDaemon.plugins.color not install";
    }

    QByteArray scaleId(FONT_RENDERING_DPI);
    if (QGSettings::isSchemaInstalled(scaleId)) {
        scaleGSettings = new QGSettings(scaleId, QByteArray(), this);
    }
}

void Widget::setcomBoxScale()
{
    int scale = 1;
    QComboBox *scaleCombox = findChild<QComboBox *>(QString("scaleCombox"));
    if (scaleCombox) {
        scale = ("100%" == scaleCombox->currentText() ? 1 : 2);
    }
    writeScale(scale);
}

void Widget::initAutoBrihgtUI()
{

    QDBusInterface *mUsdGlobalDbus = new QDBusInterface("org.ukui.SettingsDaemon",
                                                "/GlobalSignal",
                                                "org.ukui.SettingsDaemon.GlobalSignal",
                                                QDBusConnection::sessionBus(), this);;
    QDBusReply<bool> isSupportsAutoBright = mUsdGlobalDbus->call("isPresenceLightSensor");

    if (isSupportsAutoBright) {
        if (QGSettings::isSchemaInstalled(QByteArray(USD_BRIGHT_SCHEMAS))) {
            mAutoBrightSettings = new QGSettings(QByteArray(USD_BRIGHT_SCHEMAS), QByteArray(), this);
            if (mAutoBrightSettings->keys().contains("autoBrightness")) {
                mAutoBrightFrame->setChecked(mAutoBrightSettings->get(BRIGHT_KEY).toBool());
                connect(mAutoBrightFrame->switchButton(), &KSwitchButton::stateChanged, this, [=](bool status) {
                    mAutoBrightSettings->set(BRIGHT_KEY, status);
                    UkccCommon::buriedSettings(QString("display"), QString("mAutoBrightBtn"), QString("clicked"), UkccCommon::boolToString(status));
                });
            }

            connect(mAutoBrightSettings, &QGSettings::changed, this, [=](const QString &key) {
                if (!key.compare("autoBrightness")) {
                    mAutoBrightFrame->blockSignals(true);
                    mAutoBrightFrame->setChecked(mAutoBrightSettings->get(key).toBool());
                    mAutoBrightFrame->blockSignals(false);
                }
            });
        }
    } else {
        configGroup->removeWidget(mAutoBrightFrame);
        mAutoBrightFrame->deleteLater();
        mAutoBrightFrame = nullptr;
    }
}

bool Widget::isRestoreConfig()
{
    if (autoScaleChange) {
        autoScaleChange = false;
        return false;
    }
    int cnt = 15;
    QMessageBox msg(qApp->activeWindow());

    msg.addButton(tr("Not Save"), QMessageBox::RejectRole);
    QPushButton *saveBtn = msg.addButton(tr("Save"), QMessageBox::AcceptRole);

    QString config_name;
    if (mConfigChanged) {
        switch (changeItm) {
        case RESOLUTION:
            config_name = tr("resolution");
            break;
        case ORIENTATION:
            config_name = tr("orientation");
            break;
        case FREQUENCY:
            config_name = tr("frequency");
            break;
        case SCALE:
            config_name = tr("scale");
            break;
        }
        msg.setIcon(QMessageBox::Warning);

        msg.setText(QString(tr("The screen %1 has been modified, whether to save it ? "
                       "<br/>"
                       "<font style= 'color:#626c6e'>the settings will be restore after 14 seconds</font>")).arg(config_name));

        QTimer cntDown;
        QObject::connect(&cntDown, &QTimer::timeout, [&msg, &cnt, &cntDown ,&config_name]()->void {
            if (--cnt < 0) {
                cntDown.stop();
                msg.hide();
                msg.close();
            } else {
                msg.setText(QString(tr("The screen %1 has been modified, whether to save it ? "
                                       "<br/>"
                                       "<font style= 'color:#626c6e'>the settings will be restore after %2 seconds</font>")).arg(config_name).arg(cnt));

                msg.show();
            }
        });
        cntDown.start(1000);
        msg.exec();
    } else {
        if (mIsSCaleRes) {
            mIsSCaleRes = false;
            showZoomtips();
        }
        return false;
    }

    if (msg.clickedButton() == saveBtn) {
        //若点击保存后，因分辨率导致缩放发生了变化，则提示注销
        if (mIsSCaleRes) {
            mIsSCaleRes = false;
            showZoomtips();
        }
        return false;
    } else {
        if (mIsSCaleRes) {
            QStringList keys = scaleGSettings->keys();
            if (keys.contains("scalingFactor")) {
                scaleGSettings->set(SCALE_KEY,scaleres);
                compareScale();
            }
            mIsSCaleRes = false;
        }
        UkccCommon::buriedSettings(QString("display"), QString("settings not saved"), QString("settings"), config_name);
        return true;
    }
}

QString Widget::getCpuInfo()
{
    return UkccCommon::getCpuInfo();
}

bool Widget::isCloneMode()
{
    KScreen::OutputPtr output = mConfig->primaryOutput();
    if (!output) {
        return false;
    }
    if (mConfig->connectedOutputs().count() >= 2) {
        foreach (KScreen::OutputPtr secOutput, mConfig->connectedOutputs()) {
            //不能用size为(-1,-1)进行判断，刚插拔时分辨率可能会是(-1,-1)
            if (secOutput->pos() != output->pos() || !secOutput->isEnabled()) {
                return false;
            }
        }
    } else {
        return false;
    }
    return true;
}

bool Widget::isBacklight()
{
    QDBusInterface ukccIfc("com.control.center.qt.systemdbus",
                           "/",
                           "com.control.center.interface",
                           QDBusConnection::systemBus());

    QDBusReply<QString> m_reply;
    m_reply = ukccIfc.call("getDmidecodeType");
    if (m_reply.isValid()) {
        mMachineType = m_reply.value();
        if (m_reply.value() == "all in one") { //一体机
            return isBacklightAllInOne();
        } else if (m_reply.value() == "notebook") { //笔记本
            return true;
        } else if (m_reply.value() == "desktop") { //台式机
            return false;
        }
    }
    QDBusInterface brightnessInterface("org.freedesktop.UPower",
                                       "/org/freedesktop/UPower",
                                       "org.freedesktop.DBus.Properties",
                                       QDBusConnection::systemBus());
    if (!brightnessInterface.isValid()) {
        qDebug() << "Create UPower Interface Failed : " << QDBusConnection::systemBus().lastError();
        return false;
    }
    QDBusReply<QVariant> reply = brightnessInterface.call("Get", "org.freedesktop.UPower", "LidIsPresent");
    if (!reply.isValid()) {
        qDebug()<<"Get LidIsPresent Failed";
    }
    return reply.value().toBool();
}

QString Widget::getMonitorType()
{
    QString monitor = monitorComboBox->currentText();
    QString type;
    if (monitor.contains("VGA", Qt::CaseInsensitive)) {
        type = "4";
    } else {
        type = "8";
    }
    return type;
}

bool Widget::isLaptopScreen()
{
    int index = monitorComboBox->currentIndex();
    KScreen::OutputPtr output = mConfig->output(monitorComboBox->itemData(index).toInt());
    if (output->type() == KScreen::Output::Type::Panel) {
        return true;
    }
    return false;
}

bool Widget::isVisibleBrightness()
{
    if ((mIsBattery && isLaptopScreen())
            || (mIsWayland && !mIsBattery)
            || (!mIsWayland && mIsBattery)) {
        return true;
    }
    return false;
}


int Widget::getPrimaryScreenID()
{
    QString primaryScreen = getPrimaryWaylandScreen();
    int screenId;
    for (const KScreen::OutputPtr &output : mConfig->outputs()) {
        if (!output->name().compare(primaryScreen, Qt::CaseInsensitive)) {
            screenId = output->id();
        }
    }
    return screenId;
}

void Widget::setScreenIsApply(bool isApply)
{
    mIsScreenAdd = !isApply;
}

void Widget::setMulScreenVisiable()
{
    bool isMult = mConfig->connectedOutputs().count() >= 2 ? true : false;
    mMultiScreenFrame->setVisible(isMult);
    initMultScreenStatus();
}

void Widget::initMultScreenStatus()
{
    mMultiScreenCombox->blockSignals(true);
    QDBusReply<int> reply = mUsdDbus->call("getScreenMode", "ukui-control-center");
    int mode = reply.value();
    switch (mode) {
#ifndef MAVIS
    case 0:
        mMultiScreenCombox->setCurrentIndex(FIRST);
        break;
#endif
    case 1:
        mMultiScreenCombox->setCurrentIndex(CLONE);
        break;
    case 2:
        mMultiScreenCombox->setCurrentIndex(EXTEND);
        break;
#ifndef MAVIS
    case 3:
        mMultiScreenCombox->setCurrentIndex(VICE);
        break;
    //spliceScreen
#endif
    default:
        break;
    }
    setSpliceFrameVisiable(false);
    mMultiScreenCombox->blockSignals(false);
}

void Widget::updateMultiScreen()
{
    int index = 0;
    for (const KScreen::OutputPtr output : mConfig->connectedOutputs()) {
#ifndef MAVIS
        mMultiScreenCombox->setItemText(index++, Utils::outputName(output));
        //避免大于两个屏幕时把扩展、镜像覆盖
        if (index > 1) {
            break;
        }
#endif
    }
}

int Widget::updateScreenConfig()
{
    if (mConfig->connectedOutputs().size() < 1) {
        return -1;
    }
    auto *preOp = new KScreen::GetConfigOperation();
    preOp->exec();
    mPrevConfig = preOp->config()->clone();  //重新获取屏幕当前状态，通过mconfig未必能获取到正确的状态
    preOp->deleteLater();
    return 0;
}

void Widget::showZoomtips()
{
    int ret;
    QMessageBox msg(this->topLevelWidget());
    msg.setIcon(QMessageBox::Warning);
    msg.setText(tr("The zoom has been modified, it will take effect after you log off"));
    msg.addButton(tr("Log out now"), QMessageBox::AcceptRole);
    msg.addButton(tr("Later"), QMessageBox::RejectRole);

    ret = msg.exec();

    switch (ret) {
    case QMessageBox::AcceptRole:
        system("ukui-session-tools --logout");
        break;
    case QMessageBox::RejectRole:
        compareScale();
        break;
    }
}

void Widget::compareScale()
{
    for (int index = 0;index < scaleComboBox->count(); index++) {
        if (scaleComboBox->itemText(index).contains(tr("(Effective after logout)"))) {
            QString str = scaleComboBox->itemText(index);
            scaleComboBox->setItemText(index, str.split(" ").at(0));
            break;
        }
    }
    double scale = scaleGSettings->get(SCALE_KEY).toDouble();
    if (scale != qApp->devicePixelRatio())
        scaleComboBox->setItemText(scaleComboBox->currentIndex(),
                                    QString("%1%2").arg(QString::number(scale * 100) + "% ")
                                    .arg(tr("(Effective after logout)")));
}

void Widget::outputEnableChanged()
{
    changescale();
    if (mIsSCaleRes) {
        mIsSCaleRes = false;
        showZoomtips();
    }
}

void Widget::showNightWidget(bool judge)
{
    QTimer::singleShot(100, [this, judge]() {
        this->setUpdatesEnabled(false);
        mTimeModeWidget->setVisible(judge);
        if (mTimeModeWidget->comboBox()->currentIndex() == 2) {
            mCustomTimeWidget->setVisible(judge);
        } else {
            mCustomTimeWidget->setVisible(false);
        }
        mTemptWidget->setVisible(judge);
        this->setUpdatesEnabled(true);
        this->update();
    });

}

void Widget::clearOutputIdentifiers()
{
    mOutputTimer->stop();
    qDeleteAll(mOutputIdentifiers);
    mOutputIdentifiers.clear();
}

void Widget::addBrightnessFrame(QString name, bool openFlag, QString edidHash)
{
#ifdef BUILD_FOR_NO_BRIGHTNESS
    if (!mIsBattery) {
        return;
    }
#endif

    if ((mIsBattery && name != firstAddOutputName) || (UkccCommon::getProductName().startsWith("MT") && !mIsBattery))  //笔记本非内置
        return;

    if (mIsBattery) { //移除之前的亮度条，适用于kscreen返回当前为笔记本屏幕，但之前已经把第一个屏幕当做笔记本屏幕的情况
        for (int i = 0; i < BrightnessFrameV.size(); i = 0) {
            BrightnessFrameV[BrightnessFrameV.size() - 1]->deleteLater();
            BrightnessFrameV[BrightnessFrameV.size() - 1] = nullptr;
            BrightnessFrameV.pop_back();
        }
    }

    for (int i = 0; i < BrightnessFrameV.size(); ++i) {  //已经有了
        if (name == BrightnessFrameV[i]->getOutputName()) {
            if (edidHash != BrightnessFrameV[i]->getEdidHash()) {//更换了同一接口的显示器
                BrightnessFrameV[i]->updateEdidHash(edidHash);
                BrightnessFrameV[i]->setSliderEnable(false);
                BrightnessFrameV[i]->runConnectThread(openFlag);
            }
            BrightnessFrameV[i]->setOutputEnable(openFlag);
            return;
        }
    }
    BrightnessFrame *frame = nullptr;
    if (mIsBattery && name == firstAddOutputName) {
        frame = new BrightnessFrame(name, true);
    } else if(!mIsBattery) {
        frame = new BrightnessFrame(name, false, edidHash);
        if (edidI2CbusMap.isEmpty()) {
            for (QMap<QString, QString>::const_iterator it = I2CbusMap.constBegin(); it != I2CbusMap.constEnd(); ++it) {
                if (name.contains(it.key(), Qt::CaseInsensitive)) {
                    frame->setI2cbus(it.value());
                    break;
                }
            }
        } else {
            for (QMap<QString, QString>::const_iterator it = edidI2CbusMap.constBegin(); it != edidI2CbusMap.constEnd(); ++it) {
                if (edidHash == it.key()) {
                    frame->setI2cbus(it.value());
                    break;
                }
            }
        }
    }
    if (frame != nullptr) {
        connect(frame, &BrightnessFrame::sliderEnableChanged, this, [=](){
           showBrightnessFrame();
        });
        BrightnessFrameV.push_back(frame);
        mbrightnesslayout->addWidget(frame);
        frame->runConnectThread(openFlag);
        configGroup->updateShape();
    }
}

void Widget::outputAdded(const KScreen::OutputPtr &output, bool connectChanged)
{
    getAllI2Cbus();
    if (firstAddOutputName == "" && output->isConnected()) {
        firstAddOutputName = Utils::outputName(output);
    }

    if (output->type() == 7 && output->isConnected()) { //kscreen返回为笔记本屏幕,此时不再把第一个屏幕作为笔记本屏幕
        firstAddOutputName = Utils::outputName(output);
    }

    //bug:124276,特殊判断为笔记本屏幕
    if (output->type() == 14 && UkccCommon::getCpuInfo() == "Phytium,D2000/8 ULP8C" && Utils::outputName(output) == "DP-2" && output->isConnected()) {
        bool flag = true;
        for (const KScreen::ModePtr &mode : output->modes()) {
            //该机器内置屏只有1920*1080分辨率
            if (mode->size() != QSize(1920,1080)) {
                flag = false;
                break;
            }
        }
        if (flag) {
            firstAddOutputName = Utils::outputName(output);
        }
    }

    // bug#170141
    if (output->type() == 14 && UkccCommon::getCpuInfo() == "ZHAOXIN KaiXian KX-6640MA@2.2+GHz"&& Utils::outputName(output) == "DisplayPort-0" && mMachineType == "all in one") {
        firstAddOutputName = Utils::outputName(output);
    }

    if (output->isConnected()) {
        QDBusReply<QByteArray> replyEdid = dbusEdid->call("getEdid",output->id());
        const quint8 *edidData = reinterpret_cast<const quint8 *>(replyEdid.value().constData());
        QCryptographicHash hash(QCryptographicHash::Md5);
        hash.reset();
        hash.addData(reinterpret_cast<const char *>(edidData), 128);
        QString edidHash = QString::fromLatin1(hash.result().toHex());
        QString name = Utils::outputName(output);
        qInfo() << "output:" << name << "edidHash:" << edidHash;
        addBrightnessFrame(name, output->isEnabled(), edidHash);
        connectedOutputNum++;
        checkSpliceFeasibility();
    }

    if (!connectChanged) {
        connect(output.data(), &KScreen::Output::isConnectedChanged,
                this, &Widget::slotOutputConnectedChanged);
        connect(output.data(), &KScreen::Output::isEnabledChanged,
                this, &Widget::slotOutputEnabledChanged);
        for (QMLOutput *mOutput: mScreen->outputs()) {
            if (mOutput->outputPtr() = output) {
                disconnect(mOutput, SIGNAL(clicked()),
                           this, SLOT(mOutputClicked())); //避免多次连接
                connect(mOutput, SIGNAL(clicked()),
                        this, SLOT(mOutputClicked()));
            }
        }
    }

    addOutputToPrimaryCombo(output);

    if (!mFirstLoad) {
        QTimer::singleShot(2000, this, [=] {
            mainScreenButtonSelect(monitorComboBox->currentIndex());
        });
    }

    showBrightnessFrame();
}

void Widget::outputRemoved(int outputId, bool connectChanged)
{
    KScreen::OutputPtr output = mConfig->output(outputId);
    connectedOutputNum--;
    checkSpliceFeasibility();
    for (int i = 0; i < BrightnessFrameV.size(); ++i) {
        if (BrightnessFrameV[i]->getOutputName() == Utils::outputName(output)) {
            BrightnessFrameV[i]->setOutputEnable(false);
        }
    }

    if (!connectChanged) {
        if (!output.isNull()) {
            output->disconnect(this);
        }
    }

    const int index = monitorComboBox->findData(outputId);
    if (index != -1) {
        if (index == monitorComboBox->currentIndex()) {
            // We'll get the actual primary update signal eventually
            // Don't emit currentIndexChanged
            const bool blocked = monitorComboBox->blockSignals(true);
            monitorComboBox->setCurrentIndex(0);
            monitorComboBox->blockSignals(blocked);
        }

        monitorComboBox->removeItem(index);
    }

    // 检查统一输出-防止移除后没有屏幕可显示
    for (QMLOutput *qmlOutput: mScreen->outputs()) {
        if (!qmlOutput->output()->isConnected()) {
            continue;
        }
        qmlOutput->setIsCloneMode(false, false);
    }
    mIscloneMode = false;
    mainScreenButtonSelect(monitorComboBox->currentIndex());
}

void Widget::primaryOutputSelected(int index)
{
    if (!mConfig) {
        return;
    }

    const KScreen::OutputPtr newPrimary = index == 0 ? KScreen::OutputPtr() : mConfig->output(monitorComboBox->itemData(index).toInt());
    if (newPrimary == mConfig->primaryOutput()) {
        return;
    }

    mConfig->setPrimaryOutput(newPrimary);
}

// 主输出
void Widget::primaryOutputChanged(const KScreen::OutputPtr &output)
{
    Q_ASSERT(mConfig);
    int index = output.isNull() ? 0 : monitorComboBox->findData(output->id());
    if (index == -1 || index == monitorComboBox->currentIndex()) {
        return;
    }
    monitorComboBox->setCurrentIndex(index);
}

void Widget::slotIdentifyButtonClicked(bool checked)
{
    Q_UNUSED(checked);
    connect(new KScreen::GetConfigOperation(), &KScreen::GetConfigOperation::finished,
            this, &Widget::slotIdentifyOutputs);
}

void Widget::slotIdentifyOutputs(KScreen::ConfigOperation *op)
{
    if (op->hasError() || UkccCommon::isOpenkylin()) {
        return;
    }

    const KScreen::ConfigPtr config = qobject_cast<KScreen::GetConfigOperation *>(op)->config();

    mOutputTimer->stop();
    clearOutputIdentifiers();

    /* Obtain the current active configuration from KScreen */
    Q_FOREACH (const KScreen::OutputPtr &output, config->outputs()) {
        if (!output->isConnected() || !output->currentMode()) {
            continue;
        }

        const KScreen::ModePtr mode = output->currentMode();

        QQuickView *view = new QQuickView();

        view->setFlags(Qt::Tool | Qt::FramelessWindowHint);
        view->setResizeMode(QQuickView::SizeViewToRootObject);
        view->setColor(QColor(Qt::transparent)); //设置背景透明(无背景)
        view->setSource(QUrl("qrc:/qml/OutputIdentifier.qml"));
        view->installEventFilter(this);

        QQuickItem *rootObj = view->rootObject();
        if (!rootObj) {
            qWarning() << "Failed to obtain root item";
            continue;
        }

        QSize deviceSize, logicalSize;
        QPoint outputPos;
        if (output->isHorizontal()) {
            deviceSize = mode->size();
        } else {
            deviceSize = QSize(mode->size().height(), mode->size().width());
        }
#if QT_VERSION <= QT_VERSION_CHECK(5, 12, 0)
#else
        if (config->supportedFeatures() & KScreen::Config::Feature::PerOutputScaling) {
            // no scale adjustment needed on Wayland
            logicalSize = deviceSize;
            outputPos = output->pos();
        } else {
            logicalSize = deviceSize / devicePixelRatioF();
            outputPos = output->pos() / devicePixelRatioF();
        }
#endif

        rootObj->setProperty("outputName", Utils::outputName(output));
        rootObj->setProperty("modeName", Utils::sizeToString(deviceSize));

#if QT_VERSION <= QT_VERSION_CHECK(5, 12, 0)
        view->setProperty("screenSize", QRect(output->pos(), deviceSize));
#else
        view->setProperty("screenSize", QRect(outputPos, logicalSize));
#endif
        view->resize(rootObj->size().toSize());
        mOutputIdentifiers << view;
    }

    for (QQuickView *view: mOutputIdentifiers) {
        QQuickItem *rootObj = view->rootObject();
        if (mOutputClickedName == rootObj->property("outputName").toString())
            view->show();
    }

    mOutputTimer->start(2000);
}

void Widget::callMethod(QRect geometry, QString name)
{
    auto scale = 1;
    QDBusInterface waylandIfc("org.ukui.SettingsDaemon",
                              "/org/ukui/SettingsDaemon/wayland",
                              "org.ukui.SettingsDaemon.wayland",
                              QDBusConnection::sessionBus());

    QDBusReply<int> reply = waylandIfc.call("scale");
    if (reply.isValid()) {
        scale = reply.value();
    }

    QDBusMessage message = QDBusMessage::createMethodCall("org.ukui.SettingsDaemon",
                                                          "/org/ukui/SettingsDaemon/wayland",
                                                          "org.ukui.SettingsDaemon.wayland",
                                                          "priScreenChanged");
    message << geometry.x() / scale << geometry.y() / scale << geometry.width() / scale <<
        geometry.height() / scale << name;
    QDBusConnection::sessionBus().send(message);
}

QString Widget::getPrimaryWaylandScreen()
{
    QDBusInterface screenIfc("org.ukui.SettingsDaemon",
                             "/org/ukui/SettingsDaemon/wayland",
                             "org.ukui.SettingsDaemon.wayland",
                             QDBusConnection::sessionBus());
    QDBusReply<QString> screenReply = screenIfc.call("priScreenName");
    if (screenReply.isValid()) {
        return screenReply.value();
    }
    return QString();
}

void Widget::applyNightModeSlot()
{
    setNightMode(mNightModeWidget->isChecked());
}

void Widget::setMultiScreenSlot(int index)
{
    QString mode;
#ifdef MAVIS
    index = index + 2;
#endif
    switch (index) {
    case 0:
        mode = "firstScreenMode";
        break;
    case 1:
        mode = "secondScreenMode";
        break;
    case 2:
        mode = "extendScreenMode";
        break;
    case 3:
        mode = "cloneScreenMode";
        break;
#ifndef BUILD_NO_SPLICE_SCREEN
    case 4:
        spliceDialog->show();
        return;
#endif
    default:
        break;
    }
    setSpliceFrameVisiable(false);
    mUsdDbus->call("setScreenMode", mode, "ukui-control-center");
}

void Widget::delayApply()
{
    QTimer::singleShot(200, this, [=]() {
        // kds与插拔不触发应用操作
        if (!mIsScreenAdd) {
            save();
        }
        mIsScreenAdd = false;
    });
}

void Widget::save()
{
    if (!this) {
        return;
    }


    auto *preOp = new KScreen::GetConfigOperation();
    preOp->exec();
    mPrevConfig = preOp->config()->clone();  //重新获取屏幕当前状态
    preOp->deleteLater();

    const KScreen::ConfigPtr &config = this->currentConfig();
    qDebug() << Q_FUNC_INFO << config->connectedOutputs();

    bool atLeastOneEnabledOutput = false;
    Q_FOREACH (const KScreen::OutputPtr &output, config->outputs()) {
        if (output->isEnabled()) {
            atLeastOneEnabledOutput = true;
        }
        if (!output->isConnected())
            continue;

        QMLOutput *base = mScreen->primaryOutput();
        if (!base) {
            for (QMLOutput *output: mScreen->outputs()) {
                if (output->output()->isConnected() && output->output()->isEnabled()) {
                    base = output;
                    break;
                }
            }

            if (!base) {
                // WTF?
                return;
            }
        }
    }

    if (!atLeastOneEnabledOutput) {
        QMessageBox::warning(this, tr("Warning"), tr("please insure at least one output!"));
        openMonitorButton->setChecked(true);
        return;
    }

    if (!KScreen::Config::canBeApplied(config)) {
        QMessageBox::information(this,
                                 tr("Warning"),
                                 tr("Sorry, your configuration could not be applied.\nCommon reasons are that the overall screen size is too big, or you enabled more displays than supported by your GPU."));
        return;
    }
    mBlockChanges = true;
    /* Store the current config, apply settings */
    auto *op = new KScreen::SetConfigOperation(config);

    /* Block until the operation is completed, otherwise KCMShell will terminate
     * before we get to execute the Operation */
    op->exec();
    sync();

    // The 1000ms is a bit "random" here, it's what works on the systems I've tested, but ultimately, this is a hack
    // due to the fact that we just can't be sure when xrandr is done changing things, 1000 doesn't seem to get in the way
    QTimer::singleShot(1000, this,
                       [=]() {

        QString hash = config->connectedOutputsHash();
        writeFile(mDir % hash);
        sync();
        mBlockChanges = false;
        mConfigChanged = false;
        setMulScreenVisiable();
    });

    int enableScreenCount = 0;
    KScreen::OutputPtr enableOutput;
    for (const KScreen::OutputPtr &output : mConfig->outputs()) {
        if (output->isEnabled()) {
            enableOutput = output;
            enableScreenCount++;
        }
    }
    int delayTime = 0;
    if (changeItm == 1 || changeItm == 2) {
        delayTime = 900; //修改分辨率，为了保证弹出框居中，延时900ms
    }
    QTimer::singleShot(delayTime, this, [=]() {
        for (QMLOutput *qmlOutput : mScreen->outputs()) {
            if (!qmlOutput->allowResetSize()) {
                qmlOutput->setAllowResetSize(true);
            }
        }

        if (isRestoreConfig()) {
            auto *op = new KScreen::SetConfigOperation(mPrevConfig);
            op->exec();
            sync();
        }
    });
}

QVariantMap metadata(const KScreen::OutputPtr &output)
{
    QVariantMap metadata;
    metadata[QStringLiteral("name")] = output->name();
    if (!output->edid() || !output->edid()->isValid()) {
        return metadata;
    }
    metadata[QStringLiteral("fullname")] = output->edid()->deviceId();
    return metadata;
}

QString Widget::globalFileName(const QString &hash)
{
    QString s_dirPath = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation)
                        %QStringLiteral("/kscreen/");
    QString dir = s_dirPath  % QStringLiteral("outputs/");
    if (!QDir().mkpath(dir)) {
        return QString();
    }
    return QString();
}

QVariantMap Widget::getGlobalData(KScreen::OutputPtr output)
{
    QFile file(globalFileName(output->hashMd5()));
    if (!file.open(QIODevice::ReadOnly)) {
        qDebug() << "Failed to open file" << file.fileName();
        return QVariantMap();
    }
    QJsonDocument parser;
    return parser.fromJson(file.readAll()).toVariant().toMap();
}

void Widget::writeGlobal(const KScreen::OutputPtr &output)
{
    // get old values and subsequently override
    QVariantMap info = getGlobalData(output);
    if (!writeGlobalPart(output, info, nullptr)) {
        return;
    }
    QFile file(globalFileName(output->hashMd5()));
    if (!file.open(QIODevice::WriteOnly)) {
        qWarning() << "Failed to open global output file for writing! " << file.errorString();
        return;
    }

    file.write(QJsonDocument::fromVariant(info).toJson());
    return;
}

bool Widget::writeGlobalPart(const KScreen::OutputPtr &output, QVariantMap &info,
                             const KScreen::OutputPtr &fallback)
{
    info[QStringLiteral("id")] = output->hash();
    info[QStringLiteral("metadata")] = metadata(output);
    info[QStringLiteral("rotation")] = output->rotation();

    // Round scale to four digits
    info[QStringLiteral("scale")] = output->scale();

    QVariantMap modeInfo;
    float refreshRate = -1.;
    QSize modeSize;
    if (output->currentMode() && output->isEnabled()) {
        refreshRate = output->currentMode()->refreshRate();
        modeSize = output->currentMode()->size();
    } else if (fallback && fallback->currentMode()) {
        refreshRate = fallback->currentMode()->refreshRate();
        modeSize = fallback->currentMode()->size();
    }

    if (refreshRate < 0 || !modeSize.isValid()) {
        return false;
    }

    modeInfo[QStringLiteral("refresh")] = refreshRate;

    QVariantMap modeSizeMap;
    modeSizeMap[QStringLiteral("width")] = modeSize.width();
    modeSizeMap[QStringLiteral("height")] = modeSize.height();
    modeInfo[QStringLiteral("size")] = modeSizeMap;

    info[QStringLiteral("mode")] = modeInfo;

    return true;
}

bool Widget::writeFile(const QString &filePath)
{
    const KScreen::OutputList outputs = mConfig->outputs();
    const auto oldConfig = mPrevConfig;
    KScreen::OutputList oldOutputs;
    if (oldConfig) {
        oldOutputs = oldConfig->outputs();
    }
    QVariantList outputList;
    for (const KScreen::OutputPtr &output : outputs) {
        QVariantMap info;
        const auto oldOutputIt = std::find_if(oldOutputs.constBegin(), oldOutputs.constEnd(),
                                              [output](const KScreen::OutputPtr &out) {
            return out->hashMd5() == output->hashMd5();
        });
        const KScreen::OutputPtr oldOutput = oldOutputIt != oldOutputs.constEnd() ? *oldOutputIt
                                             : nullptr;
        if (!output->isConnected()) {
            continue;
        }

        writeGlobalPart(output, info, oldOutput);
        info[QStringLiteral("primary")] = output->isPrimary();
        info[QStringLiteral("enabled")] = output->isEnabled();

        auto setOutputConfigInfo = [&info](const KScreen::OutputPtr &out) {
                                       if (!out) {
                                           return;
                                       }

                                       QVariantMap pos;
                                       pos[QStringLiteral("x")] = out->pos().x();
                                       pos[QStringLiteral("y")] = out->pos().y();
                                       info[QStringLiteral("pos")] = pos;
                                   };
        setOutputConfigInfo(output->isEnabled() ? output : oldOutput);

        if (output->isEnabled()) {
            // try to update global output data
            writeGlobal(output);
        }
        outputList.append(info);
    }

    QFile file(filePath);
    if (!file.open(QIODevice::WriteOnly)) {
        qWarning() << "Failed to open config file for writing! " << file.errorString();
        return false;
    }
    file.write(QJsonDocument::fromVariant(outputList).toJson());
    qDebug() << "Config saved on: " << file.fileName();

    return true;
}

void Widget::changedSlot()
{
    mConfigChanged = true;
}

void Widget::scaleChangedSlot(double scale)
{
    if (scaleGSettings->get(SCALE_KEY).toDouble() != scale) {
        mIsScaleChanged = true;
    } else {
        mIsScaleChanged = false;
    }
    writeScale(scale);
}

void Widget::propertiesChangedSlot(QString property, QMap<QString, QVariant> propertyMap,
                                   QStringList propertyList)
{
    Q_UNUSED(property);
    Q_UNUSED(propertyList);
    if (propertyMap.keys().contains("OnBattery")) {
        mOnBattery = propertyMap.value("OnBattery").toBool();
    }
}

// 是否禁用主屏按钮
void Widget::mainScreenButtonSelect(int index)
{
    if (!mConfig || monitorComboBox->count() <= 0) {
        return;
    }

    const KScreen::OutputPtr newPrimary = mConfig->output(monitorComboBox->itemData(index).toInt());
    int connectCount = mConfig->connectedOutputs().count();

    if (mIsWayland) {
        if (!getPrimaryWaylandScreen().compare(newPrimary->name(), Qt::CaseInsensitive)) {
            monitorBtn->setEnabled(false);
        } else {
            monitorBtn->setEnabled(true);
        }
    } else {
        if (mIscloneMode || newPrimary == mConfig->primaryOutput() || mConfig->primaryOutput().isNull() || !newPrimary->isEnabled()) {
            monitorBtn->setVisible(false);
        } else {
            monitorBtn->setVisible(true);
        }
    }

    if (!newPrimary->isEnabled()) {
        scaleComboBox->setEnabled(false);
    } else {
        scaleComboBox->setEnabled(true);
    }

    // 设置是否勾选
    openMonitorButton->setEnabled(true);
    openMonitorFrame->setVisible(connectCount > 1 && !mIscloneMode);

    // 初始化时不要发射信号
    openMonitorButton->blockSignals(true);
    openMonitorButton->setChecked(newPrimary->isEnabled());
    openMonitorButton->blockSignals(false);

    mControlPanel->activateOutput(newPrimary);

    mScreen->setActiveOutputByCombox(newPrimary->id());
}

// 设置主屏按钮
void Widget::primaryButtonEnable(bool status)
{
    Q_UNUSED(status);
    if (!mConfig) {
        return;
    }
    int index = monitorComboBox->currentIndex();
    monitorBtn->setVisible(false);
    const KScreen::OutputPtr newPrimary = mConfig->output(monitorComboBox->itemData(index).toInt());
    mConfig->setPrimaryOutput(newPrimary);
}

void Widget::checkOutputScreen(bool judge)
{
    if (judge == true) {
        if (openMonitorButton->isVisible()) {  //扩展模式
            setMultiScreenSlot(EXTEND);
        }
    } else {
        int8_t enableOutputNum = 0;
        Q_FOREACH (const KScreen::OutputPtr &output, mConfig->outputs()) {
            if (output->isEnabled()) {
                enableOutputNum++;
            }
        }

        if (enableOutputNum < 2) { //两个屏幕才允许关闭
            QMessageBox::warning(this, tr("Warning"), tr("please insure at least one output!"));
            openMonitorButton->blockSignals(true);
            openMonitorButton->setChecked(true);
            openMonitorButton->blockSignals(false);
            return;
        }

        int index = monitorComboBox->currentIndex();
        KScreen::OutputPtr newPrimary = mConfig->output(monitorComboBox->itemData(index).toInt());
        QString closeOutputName = Utils::outputName(newPrimary);
#ifndef MAVIS
        if (closeOutputName == mMultiScreenCombox->itemText(0)) {
            setMultiScreenSlot(VICE);
        } else if (closeOutputName == mMultiScreenCombox->itemText(1)) {
            setMultiScreenSlot(FIRST);
        } else {
            qDebug()<<"(checkOutputScreen) closeOutputName = "<<closeOutputName;
        }
#endif
    }
    return;
}

void Widget::usdScreenModeChangedSlot(int status)
{
    if (status == USD_CLONE_MODE && !mIscloneMode) {
        mIscloneMode = true;
    } else if (status != USD_CLONE_MODE && mIscloneMode) {
        mIscloneMode = false;
    }

    int time = 1500;
    if (mIscloneMode) {
        time = 0;
        QTimer::singleShot(2500, this, [=](){ //设置镜像后，有概率会显示为扩展，原因未知，需要刷新才可以变为正常.这里处理会导致多次变化.
            this->update();
        });
    }
    QTimer::singleShot(time, this, [=](){
        if (mKdsStatus != status) {
            mKdsStatus = status;
            slotUnifyOutputs();
        }
        showBrightnessFrame();
    });
    initMultScreenStatus();

    if (m_StatusDbus->isValid()) {
        QDBusReply<bool> is_tabletmode = m_StatusDbus->call("get_current_tabletmode");
        if (is_tabletmode) {
            mMultiScreenCombox->setEnabled(false);
        } else {
            mMultiScreenCombox->setEnabled(true);
        }
    }
}

void Widget::initConnection()
{
    connect(monitorBtn, &QPushButton::clicked, this, [=](bool status){
        primaryButtonEnable(status);
        delayApply();
    });

    // Intel隐藏分辨率等调整选项
    if (UkccCommon::isTablet()) {
        mControlPanel->setVisible(false);
        scaleFrame->setVisible(false);
    }

    connect(mControlPanel, &ControlPanel::toSetScreenPos, this, [=](const KScreen::OutputPtr &output){
        for (QMLOutput *qmlOutput : mScreen->outputs()) {
            if (output && qmlOutput->output() == output) {
                qmlOutput->currentOutputSizeChanged(); //触发qml修改长和宽
                qmlOutput->setAllowResetSize(false);   //使save时不再去修改qml的长和宽，save后复位
                qmlOutput->updateRootProperties();
                mScreen->setScreenPos(qmlOutput, false);
            }
        }
    });

    connect(mControlPanel, &ControlPanel::changed, this, &Widget::changed);
    connect(this, &Widget::changed, this, [=]() {
            changedSlot();
            delayApply();
    });
    connect(mControlPanel, &ControlPanel::scaleChanged, this, &Widget::changescale);
    connect(mControlPanel, &ControlPanel::enabledChanged, this, &Widget::outputEnableChanged);

    connect(openMonitorButton, &KSwitchButton::stateChanged,
            this, [=](bool checked) {
        checkOutputScreen(checked);
        changescale();
    });


    connect(mOpenTimeHCombox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, [=]{
        if (m_colorSettings) {
            m_colorSettings->set(NIGHT_FROM_KEY,QString::number(hour_minute_to_value((mOpenTimeHCombox->currentText()).toInt(),(mQpenTimeMCombox->currentText()).toInt()),'f', 2).toDouble());
        } else {
            applyNightModeSlot();
        }
        UkccCommon::buriedSettings(QString("display"), QString("mOpenTimeHCombox"), QString("select"), mOpenTimeHCombox->currentText());
    });

    connect(mQpenTimeMCombox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, [=]{
        if (m_colorSettings) {
            m_colorSettings->set(NIGHT_FROM_KEY,QString::number(hour_minute_to_value((mOpenTimeHCombox->currentText()).toInt(),(mQpenTimeMCombox->currentText()).toInt()),'f', 2).toDouble());
        } else {
            applyNightModeSlot();
        }
        UkccCommon::buriedSettings(QString("display"), QString("mQpenTimeMCombox"), QString("select"), mQpenTimeMCombox->currentText());
    });

    connect(mCloseTimeHCombox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, [=]{
        if (m_colorSettings) {
             m_colorSettings->set(NIGHT_TO_KEY,QString::number(hour_minute_to_value((mCloseTimeHCombox->currentText()).toInt(),(mCloseTimeMCombox->currentText()).toInt()),'f', 2).toDouble());
        } else {
            applyNightModeSlot();
        }
        UkccCommon::buriedSettings(QString("display"), QString("mCloseTimeHCombox"), QString("select"), mCloseTimeHCombox->currentText());
    });

    connect(mCloseTimeMCombox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, [=]{
        if (m_colorSettings) {
            m_colorSettings->set(NIGHT_TO_KEY,QString::number(hour_minute_to_value((mCloseTimeHCombox->currentText()).toInt(),(mCloseTimeMCombox->currentText()).toInt()),'f', 2).toDouble());
        } else {
            applyNightModeSlot();
        }
        UkccCommon::buriedSettings(QString("display"), QString("mCloseTimeMCombox"), QString("select"), mCloseTimeMCombox->currentText());
    });

    connect(mTemptWidget, &SliderWidget::valueChanged, this, [=]{
        if (m_colorSettings) {
            m_colorSettings->set(NIGHT_TEMPERATURE_KEY, mTemptWidget->value());
        } else {
            applyNightModeSlot();
        }
        UkccCommon::buriedSettings(QString("display"), QString("mTemptWidget"), QString("settings"), QString::number(mTemptWidget->value()));
    });

    connect(mMultiScreenCombox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, [=](int index){
        setMultiScreenSlot(index);
        UkccCommon::buriedSettings(QString("display"), QString("mMultiScreenCombox"), QString("select"), QString::number(index));
    });

    QDBusConnection::sessionBus().connect(QString("org.ukui.SettingsDaemon"),
                                          QString("/org/ukui/SettingsDaemon/xrandr"),
                                          QString("org.ukui.SettingsDaemon.xrandr"),
                                          "screenModeChanged",
                                          this,
                                          SLOT(usdScreenModeChangedSlot(int)));

    QDBusConnection::sessionBus().connect(QString(),
                                          QString("/ColorCorrect"),
                                          "org.ukui.kwin.ColorCorrect",
                                          "nightColorConfigChanged",
                                          this,
                                          SLOT(nightChangedSlot(QHash<QString,QVariant>)));

    mOutputTimer = new QTimer(this);
    connect(mOutputTimer, &QTimer::timeout,
            this, &Widget::clearOutputIdentifiers);

    mApplyShortcut = new QShortcut(QKeySequence("Ctrl+A"), this);
    connect(mApplyShortcut, SIGNAL(activated()), this, SLOT(save()));

    connect(monitorComboBox, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
            this, [=](int index) {
        mainScreenButtonSelect(index);
        showBrightnessFrame();  //当前屏幕框变化的时候，显示，此时不判断
    });

    connect(mTimeModeWidget->comboBox(), QOverload<int>::of(&QComboBox::currentIndexChanged),[=](){
        switch (mTimeModeWidget->comboBox()->currentIndex()) {
        case 0:
            mCustomTimeWidget->hide();
            if (m_colorSettings) {
                m_colorSettings->set(AllDAY_KEY,true);
                m_colorSettings->set(AUTO_KEY,false);
            }
            break;
        case 1:
            mCustomTimeWidget->hide();
            if (m_colorSettings) {
                m_colorSettings->set(AUTO_KEY,true);
                m_colorSettings->set(AllDAY_KEY,false);
            }
            break;
        case 2:
            mCustomTimeWidget->setVisible(true);
            if (m_colorSettings) {
                m_colorSettings->set(AUTO_KEY,false);
                m_colorSettings->set(AllDAY_KEY,false);
            }
            break;
        }
        UkccCommon::buriedSettings(QString("display"), QString("mTimeModeWidget"), QString("select"), QString::number(mTimeModeWidget->comboBox()->currentIndex()));
    });

    connect(mEyesModeFrame, &SwitchWidget::stateChanged, [=](bool checked){
        if (checked && mNightModeWidget->isChecked()) {
            QMessageBox tipMsg;
            tipMsg.setIcon(QMessageBox::Warning);
            tipMsg.setText(tr("Turning on 'Eye Protection Mode' will turn off 'Color Temperature'. Continue turning it on?"));
            tipMsg.addButton(tr("Open"), QMessageBox::AcceptRole);
            tipMsg.addButton(tr("Cancel"), QMessageBox::RejectRole);
            int ret = tipMsg.exec();
            if (ret == QMessageBox::AcceptRole && m_colorSettings->keys().contains("eyeCare")) {
                m_colorSettings->set(EYES_MODE, checked);
                mNightModeWidget->blockSignals(true);
                mNightModeWidget->setChecked(false);
                mNightModeWidget->blockSignals(false);
                showNightWidget(false);
            } else {
                mEyesModeFrame->blockSignals(true);
                mEyesModeFrame->setChecked(!checked);
                mEyesModeFrame->blockSignals(false);
            }
        } else {
            if (m_colorSettings->keys().contains("eyeCare")) {
                m_colorSettings->set(EYES_MODE, checked);
            }
        }
        UkccCommon::buriedSettings(QString("display"), QString("Eye Protection Mode"), QString("clicked"), UkccCommon::boolToString(checked));
    });
    connect(mNightModeWidget, &SwitchWidget::stateChanged,[=](bool checked){
        if (checked && mEyesModeFrame->isChecked()) {
            QMessageBox tipMsg;
            tipMsg.setIcon(QMessageBox::Warning);
            tipMsg.setText(tr("Turning on 'Color Temperature' will turn off 'Eye Protection Mode'. Continue turning it on?"));
            tipMsg.addButton(tr("Open"), QMessageBox::AcceptRole);
            tipMsg.addButton(tr("Cancel"), QMessageBox::RejectRole);
            int ret = tipMsg.exec();
            if (ret == QMessageBox::AcceptRole) {
                mEyesModeFrame->blockSignals(true);
                mEyesModeFrame->setChecked(false);
                mEyesModeFrame->blockSignals(false);
                if (m_colorSettings) {
                    m_colorSettings->set(NIGHT_ENABLE_KEY,checked);
                } else {
                    applyNightModeSlot();
                }
            } else {
                mNightModeWidget->blockSignals(true);
                mNightModeWidget->setChecked(!checked);
                mNightModeWidget->blockSignals(false);
            }
        } else {
            if (m_colorSettings) {
                m_colorSettings->set(NIGHT_ENABLE_KEY,checked);
            } else {
                applyNightModeSlot();
            }
        }
        UkccCommon::buriedSettings(QString("display"), QString("mNightModeBtn"), QString("clicked"), UkccCommon::boolToString(checked));
    });

    connect(scaleComboBox, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
            this, [=](int index){
        scaleChangedSlot(scaleComboBox->itemData(index).toDouble());
        UkccCommon::buriedSettings(QString("display"), QString("screen zoom"), QString("select"), scaleComboBox->currentText());
    });
    connect(scaleGSettings,&QGSettings::changed,this,[=](QString key){
        if (!key.compare("scalingFactor", Qt::CaseSensitive)) {
            double scale = scaleGSettings->get(key).toDouble();
            if (scaleComboBox->findData(scale) == -1) {
                scale = 1.0;
            }
            scaleComboBox->blockSignals(true);
            scaleComboBox->setCurrentText(QString::number(scale * 100) + "%");
            scaleComboBox->blockSignals(false);
        }
    });

    connect(spliceDialog, &SpliceDialog::finished, this, [=](int result){
        Q_UNUSED(result);
        initMultScreenStatus();
    });
    connect(spliceDialog, &SpliceDialog::spliceScreenChanged, this, [=](QString spliceMethodText){
        //to set sth ...
        spliceMethodLabel->setText(spliceMethodText);
        setSpliceFrameVisiable(true);
        //隐藏亮度条
        mbrightnessFrame->setVisible(false);
    });
}

void Widget::setNightComponent()
{
    /* 设置时间模式 */
    mTimeModeStringList << tr("All Day") << getSunTime() << tr("Custom Time");
    mTimeModeWidget->comboBox()->insertItem(0, mTimeModeStringList.at(0));
    mTimeModeWidget->comboBox()->insertItem(1, mTimeModeStringList.at(1));
    mTimeModeWidget->comboBox()->insertItem(2, mTimeModeStringList.at(2));


    mTemptWidget->slider()->setRange(1.1*1000, 6500);
    mTemptWidget->slider()->setTracking(true);

    for (int i = 0; i < 24; i++) {
        mOpenTimeHCombox->addItem(QStringLiteral("%1").arg(i, 2, 10, QLatin1Char('0')));
        mCloseTimeHCombox->addItem(QStringLiteral("%1").arg(i, 2, 10, QLatin1Char('0')));
    }

    for (int i = 0; i < 60; i++) {
        mQpenTimeMCombox->addItem(QStringLiteral("%1").arg(i, 2, 10, QLatin1Char('0')));
        mCloseTimeMCombox->addItem(QStringLiteral("%1").arg(i, 2, 10, QLatin1Char('0')));
    }
}


void Widget::setNightMode(const bool nightMode)
{
    QDBusInterface colorIft("org.ukui.KWin",
                            "/ColorCorrect",
                            "org.ukui.kwin.ColorCorrect",
                            QDBusConnection::sessionBus());
    if (!colorIft.isValid()) {
        qWarning() << "create org.ukui.kwin.ColorCorrect failed";
        return;
    }

    if (!nightMode) {
        mNightConfig["Active"] = false;
    } else {
        mNightConfig["Active"] = true;
        if (mTimeModeWidget->comboBox()->currentIndex() == 1) {
            mNightConfig["EveningBeginFixed"] = "17:55:01";
            mNightConfig["MorningBeginFixed"] = "06:23:00";
            mNightConfig["Mode"] = 2;
        } else if (mTimeModeWidget->comboBox()->currentIndex() == 2) {
            mNightConfig["EveningBeginFixed"] = mOpenTimeHCombox->currentText() + ":"
                                                + mQpenTimeMCombox->currentText() + ":00";
            mNightConfig["MorningBeginFixed"] = mCloseTimeHCombox->currentText() + ":"
                                                + mCloseTimeMCombox->currentText() + ":00";
            mNightConfig["Mode"] = 2;
        } else if (mTimeModeWidget->comboBox()->currentIndex() == 0) {
             mNightConfig["Mode"] = 3;
        }
        mNightConfig["NightTemperature"] = mTemptWidget->value();
    }

    colorIft.call("setNightColorConfig", mNightConfig);
}

void Widget::initUiComponent()
{
    mDir = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation)
            %QStringLiteral("/kscreen/")
            %QStringLiteral("" /*"configs/"*/);

    mScaleDir = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation)
            %QStringLiteral("/kscreen/scale/");

    mIsBattery = isBacklight();

    mUPowerInterface = QSharedPointer<QDBusInterface>(
        new QDBusInterface("org.freedesktop.UPower",
                           "/org/freedesktop/UPower",
                           "org.freedesktop.DBus.Properties",
                           QDBusConnection::systemBus()));

    if (!mUPowerInterface.get()->isValid()) {
        qDebug() << "Create UPower Battery Interface Failed : " <<
            QDBusConnection::systemBus().lastError();
        return;
    }

    QDBusReply<QVariant> batteryInfo;
    batteryInfo = mUPowerInterface.get()->call("Get", "org.freedesktop.UPower", "OnBattery");
    if (batteryInfo.isValid()) {
        mOnBattery = batteryInfo.value().toBool();
    }

    mUPowerInterface.get()->connection().connect("org.freedesktop.UPower",
                                                 "/org/freedesktop/UPower",
                                                 "org.freedesktop.DBus.Properties",
                                                 "PropertiesChanged",
                                                 this,
                                                 SLOT(propertiesChangedSlot(QString, QMap<QString,QVariant>, QStringList)));

    mUkccInterface = QSharedPointer<QDBusInterface>(
                new QDBusInterface("org.ukui.ukcc.session",
                                   "/",
                                   "org.ukui.ukcc.session.interface",
                                   QDBusConnection::sessionBus()));
}

void Widget::hideComponent()
{
    if (UkccCommon::isOpenkylin() && UkccCommon::isWayland()) {
         scaleFrame->hide();
    }
#ifdef KY_SDK_SYSINFO
    mNightModeFrame->setVisible(this->mRedshiftIsValid && QString(QLatin1String(kdk_system_get_hostVirtType())) == "none");
    mNightModeLabel->setVisible(this->mRedshiftIsValid && QString(QLatin1String(kdk_system_get_hostVirtType())) == "none");
#else
    mNightModeFrame->setVisible(this->mRedshiftIsValid);
    mNightModeLabel->setVisible(this->mRedshiftIsValid);
#endif
}

void Widget::initNightStatus()
{
    QString service = "org.ukui.KWin";
    QString property = "org.ukui.kwin.ColorCorrect";
    if (UkccCommon::isOpenkylin()) {
        service = "org.kde.KWin";
        property = "org.kde.kwin.ColorCorrect";
    }


    QDBusInterface colorIft(service,
                            "/ColorCorrect",
                            "org.freedesktop.DBus.Properties",
                            QDBusConnection::sessionBus());
    if (colorIft.isValid()) {
        this->mRedshiftIsValid = true;
        QDBusReply<QVariant> reply = colorIft.call("Get", property, "available");
        if (!reply.value().toBool()) {
            mNightModeWidget->setChecked(false);
            mNightModeWidget->setEnabled(false);
            return;
        }
    } else {
        qWarning() << "create org.ukui.kwin.ColorCorrect failed";
        return;
    }
    if (m_colorSettings) {
        if (m_colorSettings->keys().contains("eyeCare")) {
            mIsEyeCareMode = m_colorSettings->get(EYES_MODE).toBool();
            mEyesModeFrame->setChecked(mIsEyeCareMode);
        }
        this->mIsNightMode = m_colorSettings->get(NIGHT_ENABLE_KEY).toBool();
        mNightModeWidget->setChecked(this->mIsNightMode && !mIsEyeCareMode);
        showNightWidget(mNightModeWidget->isChecked());
        setNightModeSetting();
        return;
    }

    QDBusMessage result = colorIft.call("nightColorInfo");

    QList<QVariant> outArgs = result.arguments();
    QVariant first = outArgs.at(0);
    QDBusArgument dbvFirst = first.value<QDBusArgument>();
    QVariant vFirst = dbvFirst.asVariant();
    const QDBusArgument &dbusArgs = vFirst.value<QDBusArgument>();

    QVector<ColorInfo> nightColor;

    dbusArgs.beginArray();
    while (!dbusArgs.atEnd()) {
        ColorInfo color;
        dbusArgs >> color;
        nightColor.push_back(color);
    }
    dbusArgs.endArray();

    for (ColorInfo it : nightColor) {
        mNightConfig.insert(it.arg, it.out.variant());
    }

    this->mIsNightMode = mNightConfig["Active"].toBool();
    mNightModeWidget->setChecked(this->mIsNightMode);
    showNightWidget(mNightModeWidget->isChecked());
    mTemptWidget->setValue(mNightConfig["CurrentColorTemperature"].toInt());
    if (mNightConfig["EveningBeginFixed"].toString() == "17:55:01" && mNightConfig["Mode"].toInt() == 2) {
        mTimeModeWidget->comboBox()->setCurrentIndex(1);
        mCustomTimeWidget->hide();
    } else if (mNightConfig["Mode"].toInt() == 3) {
        mTimeModeWidget->comboBox()->setCurrentIndex(0);
        mCustomTimeWidget->hide();
    } else {
        mTimeModeWidget->comboBox()->setCurrentIndex(2);
        QString openTime = mNightConfig["EveningBeginFixed"].toString();
        QString ophour = openTime.split(":").at(0);
        QString opmin = openTime.split(":").at(1);

        mOpenTimeHCombox->setCurrentIndex(ophour.toInt());
        mQpenTimeMCombox->setCurrentIndex(opmin.toInt());

        QString cltime = mNightConfig["MorningBeginFixed"].toString();
        QString clhour = cltime.split(":").at(0);
        QString clmin = cltime.split(":").at(1);

        mCloseTimeHCombox->setCurrentIndex(clhour.toInt());
        mCloseTimeMCombox->setCurrentIndex(clmin.toInt());
    }

}

void Widget::setNightModeSetting()
{
    if (!m_colorSettings) {
        applyNightModeSlot();
        return;
    }
    mTimeModeWidget->comboBox()->blockSignals(true);
    if (m_colorSettings->get(NIGHT_ENABLE_KEY).toBool()) {
        mNightModeWidget->blockSignals(true);
        mNightModeWidget->setChecked(true);
        mNightModeWidget->blockSignals(false);
        mEyesModeFrame->blockSignals(true);
        mEyesModeFrame->setChecked(false);
        mEyesModeFrame->blockSignals(false);

        if(m_colorSettings->get(AllDAY_KEY).toBool()) {
            mTimeModeWidget->comboBox()->setCurrentIndex(0);
        } else if(m_colorSettings->get(AUTO_KEY).toBool()) {
            mTimeModeWidget->comboBox()->setCurrentIndex(1);
        } else {
            mTimeModeWidget->comboBox()->setCurrentIndex(2);
            double openTime = m_colorSettings->get(NIGHT_FROM_KEY).toDouble();
            double cltime = m_colorSettings->get(NIGHT_TO_KEY).toDouble();
            int ophour, opmin, clhour, clmin;
            value_to_hour_minute(openTime, &ophour, &opmin);
            value_to_hour_minute(cltime, &clhour, &clmin);

            mOpenTimeHCombox->setCurrentIndex(ophour);
            mQpenTimeMCombox->setCurrentIndex(opmin);
            mCloseTimeHCombox->setCurrentIndex(clhour);
            mCloseTimeMCombox->setCurrentIndex(clmin);
        }
        showNightWidget(true);
        int value = m_colorSettings->get(NIGHT_TEMPERATURE_KEY).toInt();
        mTemptWidget->setValue(value);
    } else {
        mNightModeWidget->setChecked(false);
        showNightWidget(false);
    }
    mTimeModeWidget->comboBox()->blockSignals(false);
}

void Widget::nightChangedSlot(QHash<QString, QVariant> nightArg)
{
    if (this->mRedshiftIsValid) {
        mNightModeWidget->setChecked(nightArg["Active"].toBool());
    }
}

QString Widget::getSunTime()
{
    if (m_colorSettings) {
        if(m_colorSettings->keys().contains("nightLightScheduleAutomaticFrom")
                && m_colorSettings->keys().contains("nightLightScheduleAutomaticTo")) {
            double openTime = m_colorSettings->get(AUTO_NIGHT_FROM_KEY).toDouble();
            double cltime = m_colorSettings->get(AUTO_NIGHT_TO_KEY).toDouble();
            int ophour, opmin, clhour, clmin;
            value_to_hour_minute(openTime, &ophour, &opmin);
            value_to_hour_minute(cltime, &clhour, &clmin);
            QVector<QString> timevector;
            QVector<int> res;
            res << ophour << opmin << clhour << clmin;
            qDebug() << Q_FUNC_INFO << ophour << opmin << clhour << clmin;
            for (int i : res)
                timevector.append(QString("%1%2").arg(i < 10 ? "0" : "").arg(QString::number(i)));

            return QString("%1 (%2)").arg(tr("Follow the sunrise and sunset"))
                                    .arg(QString("%1:%2-%3:%4").arg(timevector.at(0))
                                    .arg(timevector.at(1)).arg(timevector.at(2))
                                    .arg(timevector.at(3)));
        }
    }
    return tr("Follow the sunrise and sunset");
}


/* 总结: 亮度条怎么显示和实际的屏幕状态有关,与按钮选择状态关系不大:
 * 实际为镜像模式，就显示所有屏幕的亮度(笔记本外显除外，笔记本外显任何情况均隐藏，这里未涉及)。
 * 实际为扩展模式，就显示当前选中的屏幕亮度，如果当前选中复制模式，则亮度条隐藏不显示，应用之后再显示所有亮度条;
 * 实际为单屏模式，即另一个屏幕关闭，则显示打开屏幕的亮度，关闭的显示器不显示亮度
 *
 *ps: by feng chao
*/

void Widget::showBrightnessFrame(const int flag)
{
    Q_UNUSED(flag);
    bool allShowFlag = true;
    allShowFlag = mIscloneMode;
    if (allShowFlag == true) { //镜像模式/即将成为镜像模式
        for (int i = 0; i < BrightnessFrameV.size(); ++i) {
            if (!BrightnessFrameV[i]->getOutputEnable()) {
                BrightnessFrameV[i]->setVisible(false);
                continue;
            }
            BrightnessFrameV[i]->setOutputEnable(true);
            //~ contents_path /Display/Brightness
            BrightnessFrameV[i]->setTextLabelName(tr("Brightness") + QString("(") + BrightnessFrameV[i]->getOutputName() + QString(")"));
            BrightnessFrameV[i]->setVisible(true);
        }
    } else {
        for (int i = 0; i < BrightnessFrameV.size(); ++i) {
            if (monitorComboBox->currentText() == BrightnessFrameV[i]->getOutputName() && BrightnessFrameV[i]->getOutputEnable()) {
                BrightnessFrameV[i]->setTextLabelName(tr("Brightness"));
                BrightnessFrameV[i]->setVisible(true);
                //不能break，要把其他的frame隐藏
            } else {
                BrightnessFrameV[i]->setVisible(false);
            }
        }
    }
    if (mMultiScreenCombox->currentIndex() != SPLICE) {
        mbrightnessFrame->setVisible(true);
    } else {
        mbrightnessFrame->setVisible(false);
    }
    configGroup->updateShape();
}

QList<ScreenConfig> Widget::getPreScreenCfg()
{
    QDBusMessage msg = mUkccInterface.get()->call("getPreScreenCfg");
    if(msg.type() == QDBusMessage::ErrorMessage) {
        qWarning() << "get pre screen cfg failed";
    }
    QDBusArgument argument = msg.arguments().at(0).value<QDBusArgument>();
    QList<QVariant> infos;
    argument >> infos;

    QList<ScreenConfig> preScreenCfg;
    for (int i = 0; i < infos.size(); i++){
        ScreenConfig cfg;
        infos.at(i).value<QDBusArgument>() >> cfg;
        preScreenCfg.append(cfg);
    }

    return preScreenCfg;
}

void Widget::setPreScreenCfg(KScreen::OutputList screens)
{
    QMap<int, KScreen::OutputPtr>::iterator nowIt = screens.begin();

    int posCount = 0;
    QVariantList retlist;
    while (nowIt != screens.end()) {
        ScreenConfig cfg;
        cfg.screenId = nowIt.value()->name();
        cfg.screenModeId = nowIt.value()->currentModeId();
        cfg.screenPosX = nowIt.value()->pos().x();
        cfg.screenPosY = nowIt.value()->pos().y();

        QVariant variant = QVariant::fromValue(cfg);
        retlist << variant;

        if (nowIt.value()->pos() == QPoint(0, 0)) {
            posCount++;
        }
        nowIt++;
    }

    if (posCount >= 2) {
        return;
    }

    mUkccInterface.get()->call("setPreScreenCfg", retlist);

    QVariantList outputList;
    Q_FOREACH(QVariant variant, retlist) {
        ScreenConfig screenCfg = variant.value<ScreenConfig>();
        QVariantMap map;
        map["id"] = screenCfg.screenId;
        map["modeid"] = screenCfg.screenModeId;
        map["x"] = screenCfg.screenPosX;
        map["y"] = screenCfg.screenPosY;
        outputList << map;
    }

    QString filePath = QDir::homePath() + "/.config/ukui/ukcc-screenPreCfg.json";
    QFile file(filePath);
    if (!file.open(QIODevice::WriteOnly)) {
        qWarning() << "Failed to open config file for writing! " << file.errorString();

    }
    file.write(QJsonDocument::fromVariant(outputList).toJson());
}

void Widget::changescale(QSize size)
{
    if (UkccCommon::isTablet() || (UkccCommon::isOpenkylin() && UkccCommon::isWayland()))
        return;

    mScaleSizeRes = QSize();
    if (mIscloneMode && size != QSize()) {
        mScaleSizeRes = size;
    } else {
        for (const KScreen::OutputPtr &output : mConfig->outputs()) {
            if (output->isEnabled()) {
                // 作判空判断，防止控制面板闪退
                if (output->currentMode()) {
                    if (mScaleSizeRes == QSize()) {
                        mScaleSizeRes = output->currentMode()->size();
                    } else {
                        mScaleSizeRes = mScaleSizeRes.width() < output->currentMode()->size().width()?mScaleSizeRes:output->currentMode()->size();
                    }
                } else {
                    return;
                }
            }
        }
    }

    if (mScaleSizeRes != QSize(0,0)) {
        QSize scalesize = mScaleSizeRes;
        scaleComboBox->blockSignals(true);
        scaleComboBox->clear();
        scaleComboBox->addItem("100%", 1.0);

        if (scalesize.width() > 1024 ) {
            scaleComboBox->addItem("125%", 1.25);
        }
        if (scalesize.width() == 1920 ) {
            scaleComboBox->addItem("150%", 1.5);
        }
        if (scalesize.width() > 1920) {
            scaleComboBox->addItem("150%", 1.5);
            scaleComboBox->addItem("175%", 1.75);
        }
        if (scalesize.width() >= 2160) {
            scaleComboBox->addItem("200%", 2.0);
        }
        if (scalesize.width() > 2560) {
            scaleComboBox->addItem("225%", 2.25);
        }
        if (scalesize.width() > 3072) {
            scaleComboBox->addItem("250%", 2.5);
        }
        if (scalesize.width() > 3840) {
            scaleComboBox->addItem("275%", 2.75);
        }

        double scale;
        QStringList keys = scaleGSettings->keys();
        if (keys.contains("scalingFactor")) {
            scale = scaleGSettings->get(SCALE_KEY).toDouble();
        }

        if (scaleComboBox->findData(scale) == -1) {
            //记录分辨率切换时，新分辨率不存在的缩放率，在用户点击恢复设置时写入
            mIsSCaleRes = true;

            //记录是否因分辨率导致的缩放率变化
            mIsChange = true;

            scaleres = scale;
            scale = 1.0;
        }
        scaleComboBox->setCurrentText(QString::number(scale * 100) + "%");
        scaleChangedSlot(scale);        
        scaleComboBox->blockSignals(false);

        mScaleSizeRes = QSize();
    }
}

void Widget::mOutputClicked() {
     if (mIscloneMode || mConfig->connectedOutputs().count() < 2) {
         return; //镜像模式以及显示器小于2则不检测
     }
    QMLOutput *mOutput = qobject_cast<QMLOutput *>(sender());
    mOutputClickedName = mOutput->output()->name();
    slotIdentifyButtonClicked(true);
}

bool Widget::isBacklightAllInOne()
{
    QString cmd = "";
    QByteArray buf;
    QProcess process;
    QFile file("/proc/cpuinfo");
    if(!file.open(QIODevice::ReadOnly)){
        qDebug()<<file.errorString();
    }
    buf = file.readAll();
    file.close();
    cmd = "cat /sys/class/backlight/*/max_brightness";
    //来自ukui-power-manager
    //220项目中D2000使用 cmd = "cat /sys/class/backlight/ec_bl/max_brightness";无法获取，先注释
//    if (-1 == buf.indexOf("ZHAOXIN")) {
//        if (-1 == buf.indexOf("D2000")) {
//            cmd = "cat /sys/class/backlight/*/max_brightness";
//        } else {
//            cmd = "cat /sys/class/backlight/ec_bl/max_brightness";
//        }
//    }
//    else{
//        cmd = "cat /sys/class/backlight/acpi_video1/max_brightness";
//    }
    qDebug()<<"isBacklightAllInOne --- cmd:"<<cmd;
    process.start("bash", QStringList() <<"-c" << cmd);
    process.waitForFinished();
    QString strResult =process.readAllStandardOutput()+process.readAllStandardError();
    strResult = strResult.replace("\n", "");
    QString pattern("^[0-9]*$");
    QRegExp reg(pattern);
    return reg.exactMatch(strResult);
}

void Widget::getAllI2Cbus()
{
    I2CbusMap.clear();
    //暂时仅D2000机器直接使用i2c
    // 11th该机型也使用i2c,bug#154976,后续再出问题则考虑弃用ddc,暂特殊处理
    if (!(UkccCommon::getCpuInfo().contains("D2000", Qt::CaseInsensitive) ||
          UkccCommon::getCpuInfo() == QString("11th Gen Intel(R) Core(TM) i5-1135G7 @ 2.40GHz"))) {
        return;
    }

    getEdidI2Cbus();
    if (edidI2CbusMap.isEmpty()) {
        QMap<QString, QString> msg;
        QString cmd = "find /sys/class/drm/card0-*/*/ -name '*i2c-[0-9]*'";
        QProcess process;
        process.start("bash", QStringList() <<"-c"<<cmd);
        process.waitForFinished();
        QString strResult = process.readAllStandardOutput();
        QStringList resultList = strResult.split("\n"); //所有结果

        qInfo()<<"read i2c process result = "<<resultList;
        for (int i = 0; i < resultList.size(); i++) {
            QStringList i2cList = resultList.at(i).split("/"); //切割每一行结果
            if (i2cList.size() >= 5) {
                if (!msg.keys().contains(i2cList.at(4))) {
                    //当不存在时就添加
                    msg.insert(i2cList.at(4), resultList.at(i));
                } else {
                    //已经存在，但是内容更少时也重新替换,drm中文件是嵌套的，可能存在包含关系，故做此处理
                    if (msg[i2cList.at(4)].size() > resultList.at(i).size()) {
                        msg[i2cList.at(4)] = resultList.at(i);
                    }
                }
            }
        }
        QMap<QString, QString>::const_iterator it;
        for (it = msg.constBegin(); it != msg.constEnd(); ++it) {
            qDebug()<<" ----------MAP-MSG--------- "<<it.key()<<" "<<it.value();
            //显示器名只取中间的(HDMI\VGA...)，因为后面的内容kscreen和内核提供的不一定一致
            //因此当有多个HDMI接口时此方式并不适用
            QString name = it.key().split("-").at(1);
            QStringList i2cList = it.value().split("/");
            QString i2cStr = i2cList.at(i2cList.size() - 1);
            if (!i2cStr.contains("i2c-",Qt::CaseInsensitive)) {
                i2cStr = i2cList.at(i2cList.size() - 2);
            }

            QString busNum = i2cStr.split("-").at(1);
            if (QString::number(busNum.toInt()) == busNum) {
                if (I2CbusMap.keys().contains(name)) {
                    qDebug()<<"Unable to get the correct bus number from the kernel ... "<<name;
                    I2CbusMap.clear(); //如果出现了一样的，表明有重复的接口，舍弃使用内核提供的bus号
                    return;
                }
                qInfo()<<" i2c-name = "<<name<<" *** "<<"i2c-bus="<<busNum;
                I2CbusMap.insert(name, busNum);
            }
        }
    }
    return;
}

// 获取所有显卡的节点信息
void Widget::getEdidI2Cbus()
{
    edidI2CbusMap.clear();
    QString cmd = "find /sys/class/drm/card*/*/ -name status";
    QProcess process;
    process.start("bash", QStringList() <<"-c"<<cmd);
    process.waitForFinished();
    QString strResult = process.readAllStandardOutput();
    QStringList resultList = strResult.split("\n"); //所有结果
    resultList.removeOne("");

    QMap<QString, QString> screenMap;
    for (QString s : resultList) {
        s.replace("/status", "");
        QStringList sl = s.split("/");
        if (sl.size() >= 1) {
            QString screenCardName = sl.at(sl.size() - 1);
            if (!screenMap.keys().contains(screenCardName)) {
                screenMap.insert(screenCardName, s);
            }
        }
    }
    qInfo()<<"screenMap:"<<screenMap;
    for (QMap<QString, QString>::const_iterator it = screenMap.constBegin(); it != screenMap.constEnd(); ++it) {
        QString fileName = it.value() + QString("/status");
        QFile statusFile(fileName);
        if (statusFile.exists() && statusFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
            QString str(statusFile.readAll());
            str.replace("\n", "");
            statusFile.close();
            // 是已经连接的显示器
            if (str == "connected") {
                qInfo() << "connected screen:" << it.value();
                fileName = it.value() + QString("/edid");
                QFile edidFile(fileName);
                if (edidFile.exists() && edidFile.open(QIODevice::ReadOnly)) {
                    QByteArray edidByteArray = edidFile.readAll();
                    edidFile.close();
                    QCryptographicHash hash(QCryptographicHash::Md5);
                    hash.reset();
                    const quint8 *edidData = reinterpret_cast<const quint8 *>(edidByteArray.constData());
                    hash.addData(reinterpret_cast<const char *>(edidData), 128);
                    QString edidHash = QString::fromLatin1(hash.result().toHex());
                    QString path1 = it.value() + QString("/");
                    QString path2 = it.value() + QString("/ddc/i2c-dev/");
                    QString cmdStr = QString("find ") + path1 + QString(" ") + path2 + QString(" -maxdepth 1") + QString(" -name '*i2c-[0-9]*'");
                    process.start("bash", QStringList() <<"-c"<<cmdStr);
                    process.waitForFinished();
                    strResult = process.readAllStandardOutput();
                    qDebug()<<"cmdStr:"<<cmdStr<<"resultStr:"<<strResult;
                    // 获取第一行，理论上只有一行
                    QString i2cStr = strResult.split("\n").at(0);
                    QStringList i2cStrList = i2cStr.split("/");
                    QStringList busStrList =  i2cStrList.at(i2cStrList.size() - 1).split("-");
                    if (busStrList.size() > 1) {
                        QString busNum = busStrList.at(busStrList.size() - 1);
                        if (QString::number(busNum.toInt()) == busNum && !edidI2CbusMap.keys().contains(edidHash)) {
                            edidI2CbusMap.insert(edidHash, busNum);
                        }
                    }
                }
            }
        }
    }
    qInfo() << "edidI2CbusMap:"<<edidI2CbusMap;
}

bool Widget::checkSpliceFeasibility()
{
    //dialog过程中拔插屏幕，该界面隐藏
    if (!spliceDialog->isHidden()) {
        spliceDialog->setHidden(true);
    }
    int connectedNum = mConfig->connectedOutputs().size();
    //避免初始化时多次执行
    if (connectedOutputNum != connectedNum) {
        return false;
    }
    QVector<QSize> v_resolution;
    QListView* view = dynamic_cast<QListView*>(mMultiScreenCombox->view());
    QStandardItemModel* model = dynamic_cast<QStandardItemModel*>(mMultiScreenCombox->model());
    int spliceRow = mMultiScreenCombox->findText(tr("Splice Screen"));
    //两个显示器以上，隐藏第一/第二屏
    if (connectedNum > 2) {
        if (view && model) {
            view->setRowHidden(0, true);
            view->setRowHidden(1, true);
            QStandardItem* item_0 = model->item(0);
            QStandardItem* item_1 = model->item(0);
            item_0->setFlags(item_0->flags() & ~Qt::ItemIsEnabled);
            item_1->setFlags(item_1->flags() & ~Qt::ItemIsEnabled);
        }
    } else {
        if (view && model) {
            if (view->isRowHidden(0) && view->isRowHidden(1)) {
                view->setRowHidden(0, false);
                view->setRowHidden(1, false);
                QStandardItem* item_0 = model->item(0);
                QStandardItem* item_1 = model->item(0);
                item_0->setFlags(item_0->flags() & Qt::ItemIsEnabled);
                item_1->setFlags(item_1->flags() & Qt::ItemIsEnabled);
            }
        }
    }

#ifndef BUILD_NO_SPLICE_SCREEN
    for (KScreen::OutputPtr output : mConfig->connectedOutputs()) {
        for (KScreen::ModePtr mode : output->modes()) {
            v_resolution.append(mode->size());
        }
    }

    for (int i = 0; i < v_resolution.size(); i++) {
        //存在共同的分辨率
        if (v_resolution.count(v_resolution.at(i)) == connectedNum) {
            if (view) {
                view->setRowHidden(spliceRow, false);
            }
            if (model) {
                QStandardItem* item = model->item(spliceRow);
                item->setFlags(item->flags() | Qt::ItemIsEnabled);
            }
            qDebug()<<"checkSpliceFeasibility size:"<<v_resolution.at(i)<<"  count:"<<connectedNum;
            spliceDialog->init(mConfig->connectedOutputs());
            return true;
        }
    }

    if (view) {
        view->setRowHidden(spliceRow, true);
    }

    if (model) {
        QStandardItem* item = model->item(spliceRow);
        item->setFlags(item->flags() & ~Qt::ItemIsEnabled);
    }
#endif
    return false;
}

void Widget::initSpliceFrame()
{
    QHBoxLayout *layout = new QHBoxLayout(spliceFrame);
    layout->setContentsMargins(16, 0, 16, 0);
    QLabel *spliceLabel = new QLabel(tr("Splicing Method"), spliceFrame);
    spliceMethodLabel = new QLabel(spliceFrame);
    QPushButton *changeBtn = new QPushButton(spliceFrame);
    changeBtn->setText(tr("Change"));
    changeBtn->setFixedWidth(120);
    spliceLabel->setFixedSize(118, 30);
    spliceMethodLabel->setAlignment(Qt::AlignVCenter);
    spliceMethodLabel->setContentsMargins(8,0,8,0);

    layout->addWidget(spliceLabel);
    layout->addWidget(spliceMethodLabel);
    layout->addWidget(changeBtn);
    setSpliceFrameVisiable(false);
    connect(changeBtn, &QPushButton::clicked, this, [=](){
        spliceDialog->show();
    });
    return;
}

void Widget::setSpliceFrameVisiable(bool b)
{
    spliceFrame->setVisible(b);
    return;
}

void Widget::initUi()
{
    modeGroup         = new SettingGroup(this);
    mMultiScreenFrame = new UkccFrame(modeGroup, UkccFrame::BorderRadiusStyle::Around, true);
    spliceFrame       = new UkccFrame(modeGroup, UkccFrame::BorderRadiusStyle::Around, true);
    configGroup       = new SettingGroup(this);
    monitorFrame      = new UkccFrame(configGroup, UkccFrame::BorderRadiusStyle::Around, true);
    monitorLabel      = new FixLabel(monitorFrame);
    monitorComboBox   = new QComboBox(monitorFrame);
    monitorBtn        = new QPushButton(monitorFrame);
    mControlPanel     = new ControlPanel(configGroup);
    scaleFrame        = new UkccFrame(configGroup, UkccFrame::BorderRadiusStyle::Around, true);
    scaleLabel        = new FixLabel(scaleFrame);
    scaleComboBox     = new QComboBox(scaleFrame);
    openMonitorFrame  = new UkccFrame(configGroup, UkccFrame::BorderRadiusStyle::Around, true);
    openMonitorLabel  = new FixLabel(openMonitorFrame);
    openMonitorButton = new KSwitchButton(openMonitorFrame);
    //~ contents_path /Display/Auto Brightness
    mAutoBrightFrame   = new SwitchWidget(tr("Auto Brightness"));
    mbrightnessFrame  = new UkccFrame(configGroup);
    mbrightnesslayout = new QVBoxLayout(mbrightnessFrame);

    ui->modeLayout->addWidget(modeGroup);
    modeGroup->addWidget(spliceFrame);
    modeGroup->addWidget(mMultiScreenFrame);
    ui->configLayout->addWidget(configGroup);
    configGroup->addWidget(monitorFrame);
    configGroup->addWidget(mControlPanel);
    configGroup->addWidget(scaleFrame);
    configGroup->addWidget(openMonitorFrame);
    configGroup->addWidget(mbrightnessFrame);
    configGroup->addWidget(mAutoBrightFrame);

#ifndef Nile
    mAutoBrightFrame->setVisible(false);
#endif

    QHBoxLayout *monitorLayout = new QHBoxLayout(monitorFrame);
    monitorLayout->setContentsMargins(16, 0, 16, 0);
    monitorLayout->setSpacing(16);
    monitorLayout->addWidget(monitorLabel);
    monitorLayout->addWidget(monitorComboBox);
    monitorLayout->addWidget(monitorBtn);
    monitorLabel->setFixedWidth(108);
    monitorBtn->setMinimumWidth(130);
    monitorBtn->setMaximumWidth(150);
    monitorLabel->setText(tr("monitor"));
    monitorBtn->setText(tr("as main"));

    QHBoxLayout *scaleLayout = new QHBoxLayout(scaleFrame);
    scaleLayout->setContentsMargins(16, 0, 16, 0);
    scaleLayout->setSpacing(16);
    scaleLayout->addWidget(scaleLabel);
    scaleLayout->addWidget(scaleComboBox);
    scaleLabel->setFixedWidth(108);
    scaleLabel->setText(tr("screen zoom"));

    QHBoxLayout *openMonitorLayout = new QHBoxLayout(openMonitorFrame);
    openMonitorLayout->setContentsMargins(16, 0, 16, 0);
    openMonitorLabel->setFixedWidth(108);
    openMonitorLayout->addWidget(openMonitorLabel);
    openMonitorLayout->addStretch();

    mbrightnessFrame->setContainer(true);
    mbrightnesslayout->setMargin(0);
    mbrightnesslayout->setSpacing(1);

    openMonitorLayout->addWidget(openMonitorButton);
    openMonitorLabel->setText(tr("open monitor"));
}
